//============================================================================================
/**
 * @file	pkthln_push.c
 * @brief	おしくらまんじゅう
 * @author	Nozomu Saito
 */
//============================================================================================

#include "pkthln_push.h"
#include "../../pkthln_obj_common.h"
#include "../../poke_clact.h"
#include "../pkthln_clact.h"
#include "../pkthln_act_def.h"

#include "system/snd_tool.h"
#include "system/wipe.h"
#include "system/render_oam.h"
#include "system/fontproc.h"
#include "gflib/touchpanel.h"

#include "../../pkthln_comm_pack.h"
#include "../../poke_clact_move.h"

#include "../event_se_def.h"

#include "system/arc_util.h"

#include "push_comm.h"
#include "point_ring.h"
#include "push_obj_pri.h"

#include "../../cmn_res.h"
#include "../../pkthln_poke_act.h"

#include "push_ai.h"

#include "pkthln_push_sub.h"

//成績作成用
#include "system/msgdata_util.h"
#include "msgdata/msg.naix"
#include "msgdata/msg_pokethlon.h"

#include "../pkthln_evt_info.naix"
#include "pkthev_push.naix"

#include "communication/wm_icon.h"

//同期待ち
#include "../../pkthln_frame_seq_def.h"	//for	FRAME_SEQ_CALLBACK_WAIT

// 構造体が想定のサイズとなっているかチェック
#ifdef PM_DEBUG
#ifdef _NITRO
SDK_COMPILER_ASSERT(sizeof(PUSH_PARENT_DATA) == 36);
#endif
extern DEBUG_PKTHLN_WORK DebugPkthlnWk;
#endif		//PM_DEBUG

#define PUSH_HEAP_SIZE	(0x50000)

#define PUSH_EVENT_POKE_NUM	(ENTRY_MAX*ENTRY_MEMBER_NUM_MAX)
#define PCLACT_TCB_PRIORITY	(0)

#define ARRAY_BASE_Y	(32)
#define ARRAY_BASE_X	(32)

#define DRAW_OFS_X_S	(16)
#define DRAW_OFS_Y_S	(16)
#define DRAW_OFS_X_L	(32)
#define DRAW_OFS_Y_L	(32)

#define POKE_AREA	(64)
#define SIDE_POKE_NUM	(4)	//横に並ぶポケモンの数

#define SMOG_NUM	(10)
#define SMOG_S_MAX	(5)
#define SMOG_L_MAX	(SMOG_NUM)

#define PUSH_PALETTE_NUM	(1)
#define COUNT_PALETTE_NUM	(1)
#define PUSH_SUB_PALETTE_NUM	(5)

#define SUB_ACT	(2+13)
//ポケｘ2+ラウンド+数字+ライト右+ライト左+ロゴエフェクト+旗ｘ4+ポイントｘ4
#define SUB_DISP_PAL_NUM	(2+PUSH_SUB_PALETTE_NUM)	//ポケ2+サブ画面ＯＢＪ
#define ACT_MAX	(1+1+1+5*PUSH_EVENT_POKE_NUM+RING_CNT_MAX+(2*ENTRY_MAX) + SUB_ACT)
//カウントダウン+ラストカウント+ニューレコード+ポケ12+ガイド12+影12+ポイント取得12+汗12+得点リング8+(▼マーカ+ペン)*3 +サブ画面ACT
#define PUSH_EVENT_OBJ_NUM	(PUSH_EVENT_POKE_NUM + ACT_MAX )
#define PUSH_EVENT_PAL_NUM	(PUSH_EVENT_POKE_NUM+ 1 + 1 + 1 + SUB_DISP_PAL_NUM)	//ポケ12+共有リソース+リング+汗+サブ画面

#define ONE_SEC	(30)

#define HIT_OFS_WIDTH	(8)

#define DATA_NONE	(0xff)

#define COUNT_UP_SYNC_LV1	(8)
#define COUNT_UP_SYNC_LV2	(6)
#define COUNT_UP_SYNC_LV3	(4)

#define FRAME_COUNT_LV1	(1)
#define FRAME_COUNT_LV2	(3)
#define FRAME_COUNT_LV3	(4)

#define ONE_CYCLE_TIME	(43)
#define INTERVAL_FLD_DISP_START	(2*30)	//インターバル残り2秒でフィールド表示
#define INTERVAL_TIME	(3*30)	//3秒

#define CALC_SCR_CALL_WAIT	(20)
#define POINT_UP_WAIT	(6)		//<<ポイント加算アニメが１０フレームくらいなので、それよりちょっと多い値にしておく <<仕様変更で倍速に

#define RECOV_VAL	(2)		//スタミナ回復値
#define FATIGUE_COUNT	(60)

#define RING_ALPHA_BLEND_SYNC	(5)
#define ALPHA_MAX	(12)
#define POKE_JUMP_FRAME	(6*3)
#define POINT_JUMP_FRAME (5)
#define READY_SCROLL_FRAME	(5)
#define READY_WAIT_FRAME	(20)

#define PLUS_POWER	(2)
#define PLUS_POWER_LIFE_TIME	(3)

#define MAIN_PT_ANM_OFS	(3)

#define READY_BG_START_OFS	(128)
#define READY_BG_END_OFS	(-128)

#define SND_PLAY_MARGINE	(30)

#define SE_REST_TIME		(90)

//ＢＭＰ関連
#define	REC_FONT_PAL	(15)
#define WIN_CGX_BASE	(1)
#define WIN_REC_CGX	(WIN_CGX_BASE)
#define REC_BG	(GF_BGL_FRAME3_M)

#define	COL_N_WHITE	( GF_PRINTCOLOR_MAKE( 15, 14, 0 ) )		// フォントカラー：白

#define SIDE_MIN	(16)
#define SIDE_MAX	(240)
#define HEIGHT_MIN	(16)
#define HEIGHT_MAX	(176)


#define SORT_POKE_MAX		( ENTRY_MAX*ENTRY_MEMBER_NUM_MAX )	//ポケ数
#define POKE_SORT_BUF_SIZE	(40)
//Nitro関数MATH_QSortを使用する際のソート作業領域
//必要サイズは、マニュアルによると (Log2(num)+1) * 8 byte
//今回ソートする数はSORT_POKE_MAX　=　12なので
//Log2(12)+1 * 8 < Log2(16)+1 *8 = (4+1)*8 = 40 byte 用意しとく


typedef struct PUSH_PARAM_tag
{
	int Power[5];
	int Stamina[5];
	int Speed[5];
}PUSH_PARAM;

typedef struct POS_DATA_tag
{
	u16 X;
	u16 Y;
}POS_DATA;

typedef struct LOCAL_EFF_tag
{
	u8 Seq;
	u8 AlphaSeq;
	u8 ReadySeq;
	u8 Pause;

	TCB_PTR LocalEffTcb;
	TCB_PTR ReadyTcb;
	TCB_PTR RingAlphaTcb;
	TCB_PTR PokeJumpTcb;
	TCB_PTR PointJumpTcb;
	u16 RingEffFrame;
	u16 ReadyFrame;
	u16 OldFldType;
	u16 NewFldType;
	PT_RING_CNT_PTR	RingCntPtr;
	s16 PokeJumpOfs;
	u16 PokeJumpFrame;

	int PJTarget;
	s16 PointJumpOfs;
	u16 PointJumpFrame;
	PKTHLN_PTR work;
}LOCAL_EFF;

typedef struct PUSH_POKE_PARAM_tag
{
	u8 HitRange;	//ポケモンあたり範囲	<<未使用
	u8 Move;						//移動速度
	u16 Power;						//推進力
	u16 StaminaMax;					//スタミナ最大値
	u16 StaminaNow;					//現在のスタミナ
}PUSH_POKE_PARAM;

typedef struct PUSH_POKE_tag
{
	//アクターポインタ
	POKE_ACT_PTR PokeActPtr;		//ポケモンアクター
	//ポイント
	PKTHLN_ACT_PTR	PointActPtr;
	//汗
	PKTHLN_ACT_PTR	SweatActPtr;
	//座標
	VecFx32 Pos;
	//ステート
	POKE_STATE State;

	//タッチ有効半径
///	fx32 Range;

	VecFx32 LastPoint;	//最終到達地点（親が見る）
	VecFx32 NowPoint;	//現在地点（親が見る）
	VecFx32 MoveVec;

	u8 Dir;
	u8 Push;
	u16 Score;

	u8 Fatigue;		//疲労状態
	u8 FatCount;	//疲労状態カウンタ
	u8 PlusPower;
	s8 PowerLifeTime;

	u16 MonsPal[2][16];

	PUSH_POKE_PARAM	Param;
}PUSH_POKE;

typedef struct C_ITEM_tag
{
	BOOL Valid;	//コネクトしているかどうか
	int data;
	PUSH_POKE *Poke;
	BOOL Sned;	//データの伝播が行われるか？
}C_ITEM;

typedef struct CONECT_DATA_tag
{
	C_ITEM	Item[PUSH_EVENT_POKE_NUM];	//ハッシュで持ちます
///	u16 Count;
///	u16 SearchPos;
///	int SendNum;	//伝播数
}CONECT_DATA;

typedef struct OUT_LCL_ANM_tag
{
	u16 AnmSeq;
	u16 AnmFrame;
}OUT_LCL_ANM;

static CONECT_DATA ConectData[PUSH_EVENT_POKE_NUM];

typedef struct PKTHLN_PUSH_tag
{
	GF_BGL_INI *bgl;
	GF_BGL_BMPWIN	Win;			// BMPウィンドウデータ
	int HeapID;
	//アクター
	PKTHLN_CLACT_CNT_PTR ActCntPtr;
	//カウントダウン
	CLACT_WORK_PTR	CDActPtr;


	PUSH_POKE	Poke[ENTRY_MEMBER_NUM_MAX][ENTRY_MAX];
	int TotalScore[ENTRY_MEMBER_NUM_MAX];

	TP_STATE	TpState[ENTRY_MEMBER_NUM_MAX];		//親が使う
	u8 HoldPokeNo[ENTRY_MEMBER_NUM_MAX];			//親が使う

	u8 SendNetID;									//親が使う
	u8 Sync;				//0〜10
	u8 CommTime;			//通信する時間データ10シンクで1カウントアップ　0から45、46
	u8 FieldCount;			//15秒（450シンクごとに1カウントアップ）
	u8 Interval;
	u8 EndFlg;
	u8 FldChgReq;
	u8 AddScoreReq;

	PT_RING_CNT_PTR	RingCntPtr;
	u16 NowFieldType;
	u16 ParentFieldType;
	void *TimerBgArc;
	NNSG2dScreenData *TimerScrnData;

	u8 GrayScale[PUSH_EVENT_POKE_NUM];				//グレースケールフラグ

	u8 CalcScoreCall;
	u8 CalcScoreCallWait;
	u8 GamePause;
	u8 SendPointUpPokeIdx;
	u8 SendPointNo;
	u8 PointUpWait;
	u8 PointUpNumMax;
	u8 PointUpNum;

	u8 PointUpList[PUSH_EVENT_POKE_NUM];
	u8 PointList[PUSH_EVENT_POKE_NUM];

	CMN_RES_CNT_PTR	CmnResCntPtr;
	POKE_ACT_CNT_PTR PokeActCntPtr;

	PUSH_AI_CONT_PTR AICntPtr;
	SUB_DISP_CNT_PTR SubDispCntPtr;

	//場外ローカルアニメ
	OUT_LCL_ANM  OutLclAnm[PUSH_EVENT_POKE_NUM];

	int RestThreeSec;	//ＳＥ用
	LOCAL_EFF	LocalEff;

	u8 Suicide[PUSH_EVENT_POKE_NUM];

	BOOL LocalWait;

	u8 *PokeSortBuf;
}PKTHLN_PUSH;

typedef struct NODE_DATA_tag
{
	VecFx32 *Vec;		//推進ベクトル
	u8 Child[PUSH_EVENT_POKE_NUM];		//子のインデックス格納バッファ
	u16 ChildNum;			//子の総数
	u16 Count;				//処理が終了した子の数
	VecFx32 ParToChld[PUSH_EVENT_POKE_NUM];	//親から子の中心を結んだベクトル
}NODE_DATA;

typedef struct STACK_DATA_tag
{
	u8 Data[PUSH_EVENT_POKE_NUM];
	int Point;
}STACK_DATA;

typedef struct POKE_SORT_WORK_tag
{
	u16 Idx;
	u16 Y;
}POKE_SORT_WORK;

static void SetVramBank(void);

static BOOL PUSH_Func_Phase0(PKTHLN_PTR work, u8 *seq);
static BOOL PUSH_Func_Phase1(PKTHLN_PTR work, u8 *seq);
static BOOL PUSH_Func_Phase2(PKTHLN_PTR work, u8 *seq);


static void SetPokeRectHitTable(RECT_HIT_TBL *rect, int x, int y, int sizx, int sizy);

static void BgInit(GF_BGL_INI * ini);
static void SetGraphic(PKTHLN_PUSH_PTR ptr);
static void CreateBmpWin(PKTHLN_PUSH_PTR ptr);

static void SetCommInfo(PKTHLN_PUSH_PTR ptr, PUSH_PARENT_DATA *parent);

static BOOL ControlMain(PKTHLN_PTR work);
static void SetDraw(PKTHLN_PTR work);
static void CommMain(PKTHLN_PTR work);
static void MovePoke(PKTHLN_PTR work);

static void GetLastPoint(const u8 inTpX, const u8 inTpY, const VecFx32 *inNowPoint, const fx32 inRange, VecFx32 *outPoint);
///static void GetAlivePokeAndPlayerNum(PKTHLN_PUSH_PTR ptr, u8 *outPlayerNum, u8 *outPokeNum);

static u8 CheckPokeTouch(PKTHLN_PUSH_PTR ptr, const u8 inNetID, const u16 inX, const u16 inY);
static BOOL CheckCircle(PUSH_POKE * poke1, PUSH_POKE * poke2);
static void MakeConectData(PKTHLN_PUSH_PTR ptr);
static BOOL CheckMovable(PKTHLN_PUSH_PTR ptr, PUSH_POKE *poke,
		const u8 inIdx, const VecFx32 *inMoveVec);

static void PushExecute(PKTHLN_PUSH_PTR ptr);
static u8 PushData(STACK_DATA *Stack, const u8 inData);
static u8 PopData(STACK_DATA *Stack);
static void CalcVec(const VecFx32 *inVec1, const VecFx32 *inVec2, VecFx32 *outVec);
static fx32 GetCos( const VecFx32 *inVec1, const VecFx32 *inVec2 );
static void CheckScore(PKTHLN_PUSH_PTR ptr);

static void FillTimerBG(const u8 inTime, GF_BGL_INI *bgl);
static void Fill(const u8 inTime, GF_BGL_INI *bgl);

static void RevivePoke(PKTHLN_PUSH_PTR ptr);
static BOOL IsRetire(PKTHLN_PUSH_PTR ptr, const int inNetID);

static void RecoverStamina(PUSH_POKE *outPoke);
static void SetPokeParam(PKTHLN_PTR work, const PUSH_PARAM *inData, const u8 inNetID, const u8 inIdx, PUSH_POKE *outPoke);

static void SetLocalEff(LOCAL_EFF *local, const int inOldFldType, const int inNewFldType, PKTHLN_PTR work);
static void LocalEffMainTcb(TCB_PTR tcb, void* work);
static void RingAlphaTcb(TCB_PTR tcb, void* work);
static void ReadyTcb(TCB_PTR tcb, void* work);
static void PokeJumpTcb(TCB_PTR tcb, void* work);
static void StopLocalEff(LOCAL_EFF *local);

static void PointJumpTcb(TCB_PTR tcb, void* work);
static void SetPointJump(LOCAL_EFF *local, const u8 inPokeIdx);
static void PointJump(PKTHLN_PTR work, LOCAL_EFF *local, POKE_ACT_PTR poke_ptr, const u8 inPokeIdx, const POKE_DIR inDir);

static void SetRecordStr(PKTHLN_PUSH_PTR ptr, const int inPoint);
static BOOL CheckFldOutRange(POKE_ACT_PTR poke_ptr, const fx32 inX, const fx32 inY);

static s32 CompFunc(void *elem1, void *elem2);
static void SortPoke(PKTHLN_PUSH_PTR ptr, PUSH_PARENT_DATA *parent);

PKTHLN_FUNC PushFuncTbl[] = {
	PUSH_Func_Phase0,
	PUSH_Func_Phase1,
	PUSH_Func_Phase2,
};

enum {
	PUSH_SEQ_PHASE0,
	PUSH_SEQ_PHASE1,
	PUSH_SEQ_PHASE2,
};

typedef struct POSDATA_tag
{
	s16 X;
	s16 Y;
}POSDATA;

//初期配置テーブル
static const POS_DATA InitPos[ENTRY_MEMBER_NUM_MAX][ENTRY_MAX] = {
	{ { 40, 40},{ 40, 72},{ 88, 40} },
	{ {216, 40},{168, 40},{216, 72} },
	{ { 40,168},{ 88,168},{40,146} },
	{ {216,168},{216,146},{168,168} },
};

//仕様変更でジャンプフレームを縮小
static int PointJumpArray[POINT_JUMP_FRAME] = {
	-4,-2,0,2,4
};

static int PokeJumpArray[POKE_JUMP_FRAME] = {
	-3,-2,-1,1,2,3,-3,-2,-1,1,2,3,-3,-2,-1,1,2,3
};

//----------レコードＢＭＰ---------------
//ＢＮＰウィンドウデータ
static const BMPWIN_DAT RecordBmpData = {
		REC_BG, WIN_REC_PX, WIN_REC_PY,
		WIN_REC_SX, WIN_REC_SY, REC_FONT_PAL, WIN_REC_CGX
};

#include "system/arc_tool.h"


//--------------------------------------------------------------------------------------------
/**
 * 初期化関数
 *
 * @param	work		ポケスロンワークポインタ
 * @param	*pParam		パラメータ
 *
 * @return	TRUE
 */
//--------------------------------------------------------------------------------------------
PTH_RC PE_PUSH_InitFunc(PKTHLN_PTR work, void *pParam)
{
	PKTHLN_PUSH_PTR ptr = PTFrame_GetEventWorkPtr(work);
	u8 seq = PTFrame_GetSubSeq(work);
	switch(seq){
	case 0:
		{
			int heap_id;
			sys_CreateHeap( HEAPID_POKETHLON, HEAPID_PT_PUSH, PUSH_HEAP_SIZE );
			heap_id = HEAPID_PT_PUSH;

			sys_VBlankFuncChange( NULL, NULL );	// VBlankセット
			sys_HBlankIntrSet( NULL,NULL );		// HBlankセット

			GF_Disp_GX_VisibleControlInit();
			GF_Disp_GXS_VisibleControlInit();
			GX_SetVisiblePlane( 0 );
			GXS_SetVisiblePlane( 0 );

			//VRAMバンク割り当て
			SetVramBank();
			//アプリケーションメモリー
			ptr = PTFrame_AllocEventWork(work, sizeof(PKTHLN_PUSH));
			MI_CpuClear8( ptr, sizeof(PKTHLN_PUSH));

			//ソートバッファアロック
			{
				ptr->PokeSortBuf = sys_AllocMemory(heap_id, POKE_SORT_BUF_SIZE);
				MI_CpuClear8( ptr->PokeSortBuf, POKE_SORT_BUF_SIZE);
			}

			//BGLアロケーション
			ptr->bgl = GF_BGL_BglIniAlloc(heap_id);

			//レコード表示ＢＧのセット
			PTFrame_SetRecBGMask(work, GX_PLANEMASK_BG3);

			{
				CHAR_MANAGER_MAKE cm;
				cm.CharDataNum = PUSH_EVENT_OBJ_NUM;
				cm.VramTransAreaMain = 256*1024;
				cm.VramTransAreaSub = 16*1024;
				cm.heap = heap_id;

				//キャラ・パレットマネージャ初期化
				PKTHLN_OBJ_COMMON_InitCharPlttManager(	&cm,
														PUSH_EVENT_PAL_NUM,
														heap_id,
														GX_OBJVRAMMODE_CHAR_1D_256K,
														GX_OBJVRAMMODE_CHAR_1D_32K);
			}

			OS_Printf("MAPPING_MODE = %d,%d\n",GX_OBJVRAMMODE_CHAR_1D_256K, GX_OBJVRAMMODE_CHAR_1D_32K);

			// OAMマネージャーの初期化
			NNS_G2dInitOamManagerModule();

			// 共有OAMマネージャ作成
			// レンダラ用OAMマネージャ作成
			// ここで作成したOAMマネージャをみんなで共有する
			REND_OAMInit(
					0, 126,		// メイン画面OAM管理域
					0, 32,		// メイン画面アフィン管理領域
					0, 126,		// サブ画面OAM管理領域
					0, 32,		// サブ画面アフィン管理領域
					heap_id);
			ptr->HeapID = heap_id;
		}

		//タッチフォントロード
		FontProc_LoadFont(FONT_TOUCH, ptr->HeapID);

		BgInit(ptr->bgl);

		//BMP
		CreateBmpWin(ptr);

		//下画面をメインにする
		sys.disp3DSW = DISP_3D_TO_SUB;
		GF_Disp_DispSelect();

		//次のシーケンスへ
		PTFrame_IncSubSeq(work);
		break;
	case 1:
		ptr->SubDispCntPtr = PushSub_Init( ptr->HeapID, ptr->bgl, work);
		ptr->AICntPtr = PushAI_Init(ptr->HeapID,
				ENTRY_MEMBER_NUM_MAX-PTFrame_GetPlayerNum(work), PTFrame_GetGameType(work));
		ptr->CmnResCntPtr = CmnRes_Init( ptr->HeapID,
										 CMN_RES_ALL_BIT|CMN_RES_PEN_M_BIT|CMN_RES_CUR_BIT,
										 NNS_G2D_VRAM_TYPE_2DMAIN );
		ptr->RingCntPtr = PtRing_Init(ptr->HeapID);
		ptr->LocalEff.RingCntPtr = ptr->RingCntPtr;
		PushSub_SetupPokeGraphic(ptr->SubDispCntPtr);

		//▼マーカ初期化
		PTFrame_InitPosMarker(work);

		//次のシーケンスへ
		PTFrame_IncSubSeq(work);
		break;
	case 2:
		{
			int i;
			CLACT_WORK_PTR act_ptr;
			PKTHLN_ACT_SETUP_PRM param = {
				ACT_MAX,5,{5,5,5,5}
			};
			ptr->ActCntPtr = PkthlnClAct_Init(ptr->HeapID, &param);

			//上下画面幅設定
			PkthlnClAct_SetDispDistance(ptr->ActCntPtr,
										0, 0,
										0, SUB_DISP_DISTANCE );
			//ポケモンアクター
			ptr->PokeActCntPtr = PokeAct_Init( ptr->HeapID, PUSH_EVENT_POKE_NUM, PRI_POKE_MINE,
									  ptr->CmnResCntPtr, PkthlnClAct_GetClActSetAdr(ptr->ActCntPtr) );

			//ポケモンアクターにアクターセットポインタを渡して初期化
///			PCLACT_Init(ptr->PclActCntPtr, PUSH_EVENT_POKE_NUM,
///					PkthlnClAct_GetClActSetAdr(ptr->ActCntPtr));

			PkthlnClAct_SetResObjCode(ptr->ActCntPtr, 0, RES_CODE_PUSH);
			PkthlnClAct_SetResObjCode(ptr->ActCntPtr, 1, RES_CODE_PUSH_OBJ);
			PkthlnClAct_SetResObjCode(ptr->ActCntPtr, 2, RES_CODE_TRNS_POKE1);
			PkthlnClAct_SetResObjCode(ptr->ActCntPtr, 3, RES_CODE_TRNS_POKE2);
			PkthlnClAct_SetResObjCode(ptr->ActCntPtr, 4, RES_CODE_PSUB_OBJ);
			//
			PkthlnClAct_SetChar( ptr->ActCntPtr,
							ARC_PKTHEV_PUSH, NARC_pkthev_push_push_NCGR,
							RES_CODE_PUSH, NNS_G2D_VRAM_TYPE_2DMAIN);
			PkthlnClAct_SetPaltt( ptr->ActCntPtr,
							ARC_PKTHEV_PUSH, NARC_pkthev_push_push_NCLR,
							RES_CODE_PUSH, NNS_G2D_VRAM_TYPE_2DMAIN, PUSH_PALETTE_NUM	);
			PkthlnClAct_SetCell( ptr->ActCntPtr,
							ARC_PKTHEV_PUSH, NARC_pkthev_push_push_NCER, RES_CODE_PUSH	);
			PkthlnClAct_SetAnm(	ptr->ActCntPtr,
							ARC_PKTHEV_PUSH, NARC_pkthev_push_push_NANR, RES_CODE_PUSH	);

			PkthlnClAct_SetChar( ptr->ActCntPtr,
							ARC_PKTHEV_PUSH, NARC_pkthev_push_push_obj_sub_NCGR,
							RES_CODE_PUSH_OBJ, NNS_G2D_VRAM_TYPE_2DMAIN);
			PkthlnClAct_SetPaltt( ptr->ActCntPtr,
							ARC_PKTHEV_PUSH, NARC_pkthev_push_push_obj_sub_NCLR,
							RES_CODE_PUSH_OBJ, NNS_G2D_VRAM_TYPE_2DMAIN, PUSH_PALETTE_NUM	);
			PkthlnClAct_SetCell( ptr->ActCntPtr,
							ARC_PKTHEV_PUSH, NARC_pkthev_push_push_obj_sub_NCER, RES_CODE_PUSH_OBJ	);
			PkthlnClAct_SetAnm(	ptr->ActCntPtr,
							ARC_PKTHEV_PUSH, NARC_pkthev_push_push_obj_sub_NANR, RES_CODE_PUSH_OBJ	);

			PkthlnClAct_SetChar( ptr->ActCntPtr,
							ARC_PKTHEV_PUSH, NARC_pkthev_push_push_obj_sub02_NCGR,
							RES_CODE_PSUB_OBJ, NNS_G2D_VRAM_TYPE_2DSUB);
			PkthlnClAct_SetPaltt( ptr->ActCntPtr,
							ARC_PKTHEV_PUSH, NARC_pkthev_push_push_obj_sub02_NCLR,
							RES_CODE_PSUB_OBJ, NNS_G2D_VRAM_TYPE_2DSUB, PUSH_SUB_PALETTE_NUM	);
			PkthlnClAct_SetCell( ptr->ActCntPtr,
							ARC_PKTHEV_PUSH, NARC_pkthev_push_push_obj_sub02_NCER, RES_CODE_PSUB_OBJ	);
			PkthlnClAct_SetAnm(	ptr->ActCntPtr,
							ARC_PKTHEV_PUSH, NARC_pkthev_push_push_obj_sub02_NANR, RES_CODE_PSUB_OBJ	);

			PushSub_SetTrnsPokeRes(ptr->ActCntPtr, ptr->SubDispCntPtr);
			//トランス
			PkthlnClAct_Trans(ptr->ActCntPtr);

			//得点リング
			for (i=0;i<RING_CNT_MAX;i++){
				PkthlnClAct_SetActor(ptr->ActCntPtr, 2, NNS_G2D_VRAM_TYPE_2DMAIN, RES_CODE_PUSH, ACT_CODE_RING);
			}

			//ポイント・汗
			for(i=0;i<PUSH_EVENT_POKE_NUM;i++){
				PkthlnClAct_SetActor(ptr->ActCntPtr, 1, NNS_G2D_VRAM_TYPE_2DMAIN, RES_CODE_PUSH_OBJ, ACT_CODE_POINT);
				PkthlnClAct_SetActor(ptr->ActCntPtr, 1, NNS_G2D_VRAM_TYPE_2DMAIN, RES_CODE_PUSH_OBJ, ACT_CODE_SWEAT);
			}

			//リング
			PtRing_SetRingAct(ptr->RingCntPtr, ptr->ActCntPtr);

			//ポイント・汗
			for(i=0;i<PUSH_EVENT_POKE_NUM;i++){
				ptr->Poke[i/ENTRY_MAX][i%ENTRY_MAX].PointActPtr =
					PkthlnClAct_GetActPtr(ptr->ActCntPtr, RES_CODE_PUSH_OBJ, ACT_CODE_POINT);
				act_ptr = PkthlnClAct_GetClActWorkPtr(ptr->Poke[i/ENTRY_MAX][i%ENTRY_MAX].PointActPtr);
				//プライオリティセット
				CLACT_DrawPriorityChg( act_ptr, PRI_POINT );

				ptr->Poke[i/ENTRY_MAX][i%ENTRY_MAX].SweatActPtr =
					PkthlnClAct_GetActPtr(ptr->ActCntPtr, RES_CODE_PUSH_OBJ, ACT_CODE_SWEAT);
				act_ptr = PkthlnClAct_GetClActWorkPtr(ptr->Poke[i/ENTRY_MAX][i%ENTRY_MAX].SweatActPtr);
				//プライオリティセット
				CLACT_DrawPriorityChg( act_ptr, PRI_SWEAT );

			}
			//カウントダウンアクター
			{
				CLACT_WORK_PTR	*act_adr;
				act_adr = PTFrame_SetCountDown( work, 0, ptr->CmnResCntPtr, ptr->ActCntPtr );
				ptr->CDActPtr = *act_adr;
				//プライオリティセット
				CLACT_DrawPriorityChg( ptr->CDActPtr, PRI_COUNT );
			}
			//サブ画面ポケモン
			PushSub_SetPoke(ptr->ActCntPtr, ptr->SubDispCntPtr);
			//サブ画面ポケ以外のＯＢＪ
			PushSub_SetObj(ptr->ActCntPtr, ptr->SubDispCntPtr);

			//
		}
		//次のシーケンスへ
		PTFrame_IncSubSeq(work);
		break;
	case 3:
		{
			int i;
			MONS_INFO info[PUSH_EVENT_POKE_NUM];
			PCLACT_SET_PARAM param;

			for(i=0;i<PUSH_EVENT_POKE_NUM;i++){
				PTFrame_SetMonsInfo(work, i/ENTRY_MAX, i%ENTRY_MAX, &info[i]);

				param.ShadowPos[i] =
					PTFrame_GetPokeShdwPosType(PTFrame_GetPkthlnParam(work, i/ENTRY_MAX, i%ENTRY_MAX));

				//パレット生成
				{
					PUSH_POKE *push_poke;
					push_poke = &ptr->Poke[i/ENTRY_MAX][i%ENTRY_MAX];
					PCLACT_GetPalData(&info[i], ptr->HeapID, (u8*)&push_poke->MonsPal[0][0]);
					MI_CpuCopy8(push_poke->MonsPal[0], push_poke->MonsPal[1], 16*2);
					//グレースケールパレット
					PaletteGrayScale(push_poke->MonsPal[1], 16);
				}
			}
			param.Quick = 0;
			param.BGPriority = 1;
			param.Trans = 0;
			param.ResVramType = NNS_G2D_VRAM_TYPE_2DMAIN;
			param.DrawArea = NNS_G2D_VRAM_TYPE_2DMAIN;

			PokeAct_SetPokeActor(	ptr->PokeActCntPtr, PUSH_EVENT_POKE_NUM,
									info, &param,
									PCLACT_TCB_PRIORITY,
									0 );

		}
		//次のシーケンスへ
		PTFrame_IncSubSeq(work);
		break;
	case 4:
		if ( PokeAct_CheckActSetTask(ptr->PokeActCntPtr) ){
			PEN_POS	pen_pos[ENTRY_MAX];
			EVT_HIT_DATA hit_data;
			int i;
			int my_net_id;

			my_net_id = PTFrameGetCurrentID(work);

			PTFrame_SetDefaultVBlankFunc(ptr->bgl);	// VBlankセット
			//描画を許可
			PTFrame_SetDraw(work, TRUE);

			ArchiveDataLoad(hit_data.Data, ARC_PKTHEVT_PARAM, NARC_pkthln_evt_info_push_hit_bin);

			//ポケセルアクター可視化
			for (i=0;i<PUSH_EVENT_POKE_NUM;i++){
				POKE_ACT_PTR poke_ptr = PokeAct_GetPokeActPtr(ptr->PokeActCntPtr, i);
				PokeAct_DispCnt(poke_ptr, 1);	//表示

				//あたり判定データセット
				{
					HIT_TYPE hit_type;
					hit_type = PTFrame_GetPokeHitType(PTFrame_GetPkthlnParam(work, i/ENTRY_MAX, i%ENTRY_MAX));
					PokeAct_SetHitData(poke_ptr, hit_data.Data[hit_type-1].Ofs, hit_data.Data[hit_type-1].Range);
///					OS_Printf("hitdata::%d,%d\n",hit_data.Data[hit_type-1].Ofs,hit_data.Data[hit_type-1].Range);
				}

				//ポケモン初期位置
				{
					const MONS_INFO *info;
					PUSH_POKE *push_poke;
					int space;
					POKE_ACT_PTR poke_ptr = PokeAct_GetPokeActPtr(ptr->PokeActCntPtr, i);
					PCLACT_PTR	pclact_ptr = PokeAct_GetPclActPtr(poke_ptr);
					VecFx32 aff_vec = {0,0,0};

					push_poke = &ptr->Poke[i/ENTRY_MAX][i%ENTRY_MAX];
					push_poke->PokeActPtr = poke_ptr;
					push_poke->State = POKE_ALIVE;

					space = PCLACT_GetSpaceHeight(pclact_ptr);

					info = PCLACT_GetMonsInfo(pclact_ptr);
					if (info->CellType){
						aff_vec.x = (BIG_POKE_SIZE/2)*FX32_ONE;
						aff_vec.y = (space+(BIG_POKE_SIZE-space)/2)*FX32_ONE;
					}else{
						aff_vec.x = (SMALL_POKE_SIZE/2)*FX32_ONE;
						aff_vec.y = (space+(SMALL_POKE_SIZE-space)/2)*FX32_ONE;
					}

					//テーブルで位置決定
					{
						int sx,sy, tx,ty;
						int range;
						//影の位置
						sx = InitPos[i/ENTRY_MAX][i%ENTRY_MAX].X;
						sy = InitPos[i/ENTRY_MAX][i%ENTRY_MAX].Y;

						push_poke->Dir = POKE_DIR_DOWN;
						//向きセット
						PokeAct_SetDir(poke_ptr, POKE_DIR_DOWN);
						//アクター位置セット
////						PokeAct_SetPos(poke_ptr, x+ofs_x, y+ofs_y, TRUE);
						PokeAct_SetPosShadow(poke_ptr, sx, sy);

						//タッチ半径セット
						range =
							PTFrame_GetPokeTouchRange();
						PokeAct_SetTouchRange(poke_ptr, range);
///						push_poke->Range = range*FX32_ONE;

						//タッチ中心座標取得
						PokeAct_GetTouchPosByShadowPos(poke_ptr, sx, sy, &tx, &ty);

						push_poke->Pos.x = tx*FX32_ONE;
						push_poke->Pos.y = ty*FX32_ONE;
						push_poke->NowPoint.x = tx*FX32_ONE;
						push_poke->NowPoint.y = ty*FX32_ONE;
						push_poke->LastPoint.x = tx*FX32_ONE;
						push_poke->LastPoint.y = ty*FX32_ONE;

						//ポケモンプライオリティ(自分のポケは表示優先度が高い)
						if (i/ENTRY_MAX == PTFrameGetCurrentID(work)){
							PokeAct_SetPriority(poke_ptr, PRI_POKE_MINE);
						}else{
							PokeAct_SetPriority(poke_ptr, PRI_POKE);
						}

						//アフィンセット＜＜落下したときのみアフィンセットするように変更
						///PokeAct_SetAffine(poke_ptr, CLACT_AFFINE_NORMAL);
						//アフィン座標セット
						PokeAct_SetAffineVec(poke_ptr, &aff_vec);

						//親のとき、初回送信データを作成
						if (PTFrameGetCurrentID(work) == COMM_PARENT_ID){
							COMM_EVENT_COMMON_DATA *data;
							PUSH_PARENT_DATA *parent;
							data = PTFrame_GetEvtComCmnData(work);
							parent = PKTHLN_CommPack_GetData(&data->SendShareData);
							SetCommInfo(ptr, parent);
/**
							//データ格納
							parent->PokeX[i] = tx;
							parent->PokeY[i] = ty;
							parent->PokeSt |= (1 << (i*2));		//生存フラグ
							parent->PokeSt |= (PUSH_EVENT_POKE_NUM<<28);
*/
						}

						//自分のポケ3体のペン表示座標を保存
						if ( (i/ENTRY_MAX)==my_net_id ){
							CLACT_WORK_PTR	act_ptr;
							pen_pos[i%ENTRY_MAX].X = tx;
							pen_pos[i%ENTRY_MAX].Y = ty;
							//▼マーカーセット
							act_ptr = PTFrame_SetPosMarker( work, poke_ptr, ptr->CmnResCntPtr,
									    					PkthlnClAct_GetClActSetAdr(ptr->ActCntPtr), 1);
							//プライオリティセット
							CLACT_DrawPriorityChg( act_ptr, PRI_POS_MARKER );
						}
					}//テーブルで位置決定
				} //ポケモン初期位置
			}	//end for

			//ペン表示
			PTFrame_SetPen( work, 0, ptr->CmnResCntPtr, ptr->ActCntPtr,
						    NNS_G2D_VRAM_TYPE_2DMAIN, ENTRY_MAX,  pen_pos);

			{
				PUSH_PARAM data;
				int i;
				PUSH_POKE *push_poke;
				ArchiveDataLoad(&data, ARC_PKTHEVT_PARAM, NARC_pkthln_evt_info_push_bin);
#if 0
				{
					int m;
					for(m=0;m<5;m++){
						OS_Printf("push_prm:%d,%d,%d\n",
								data.Power[m], data.Stamina[m], data.Speed[m]);
					}
				}
#endif
				for(i=0;i<ENTRY_MEMBER_NUM_MAX;i++){
					int j;
					//親の判定データ初期化
					ptr->HoldPokeNo[i] = PUSH_EVENT_POKE_NUM;
					//パラメータ格納
					for(j=0;j<ENTRY_MAX;j++){
						push_poke = &ptr->Poke[i][j];
						SetPokeParam(work, &data, i, j, push_poke);

						//AI用にデータをセットアップ
						PushAI_Setup(	ptr->AICntPtr, i*ENTRY_MAX+j,
										push_poke->Param.Power,
										&(push_poke->Param.StaminaNow),
										&(push_poke->NowPoint),
										&(push_poke->State),
										&(push_poke->LastPoint),
										push_poke->PokeActPtr );
					}
				}
			}

			//フィールドタイプセット
			ptr->NowFieldType = 0;
			ptr->ParentFieldType = 0;
			//ローカルエフェクト、ポイントジャンプ対象ポケ初期化
			ptr->LocalEff.PJTarget = PUSH_EVENT_POKE_NUM;

			PtRing_MakeField(ptr->RingCntPtr, ptr->NowFieldType);
			G2_SetBlendAlpha( GX_BLEND_PLANEMASK_NONE, GX_BLEND_PLANEMASK_BG0,
					ALPHA_MAX, 16-ALPHA_MAX );
			//得点ポケ初期化
			ptr->SendPointUpPokeIdx = PUSH_EVENT_POKE_NUM;

			SetGraphic(ptr);
			PushSub_WriteWinInfo(ptr->SubDispCntPtr);

			//ＯＢＪの表示
			GF_Disp_GX_VisibleControl( GX_PLANEMASK_OBJ, VISIBLE_ON );		// MAIN DISP OBJ ON
			GF_Disp_GXS_VisibleControl( GX_PLANEMASK_OBJ, VISIBLE_ON );		// SUB DISP OBJ ON

			//通信アイコン
			WirelessIconEasyPokethlon( NNS_G2D_VRAM_TYPE_2DMAIN );

			//次のシーケンスへ
			PTFrame_IncSubSeq(work);

		}
		break;
	case 5:
		//初期化終了
		sys_PrintHeapFreeSize( ptr->HeapID );
		return PTH_RC_END;
	}
	return PTH_RC_LOOP;
}

//--------------------------------------------------------------------------------------------
/**
 * 描画関数
 *
 * @param	work		ポケスロンワークポインタ
 * @param	*pParam		パラメータ
 *
 * @return	TRUE
 */
//--------------------------------------------------------------------------------------------
BOOL PE_PUSH_DrawFunc(PKTHLN_PTR work, void *pParam)
{
	PKTHLN_PUSH_PTR ptr = PTFrame_GetEventWorkPtr(work);

	PkthlnClAct_Draw(ptr->ActCntPtr);
	return TRUE;
}

//--------------------------------------------------------------------------------------------
/**
 * 競技結果計算関数
 *
 * @param	work		ポケスロンワークポインタ
 * @param	*pParam		パラメータ
 *
 * @return	TRUE
 */
//--------------------------------------------------------------------------------------------
BOOL PE_PUSH_ResultFunc(PKTHLN_PTR work, void *pParam)
{
	int i,j;
	RSLT_PTR result_ptr;
	PKTHLN_PUSH_PTR ptr = PTFrame_GetEventWorkPtr(work);

	OS_Printf("競技結果データ作成\n");

	result_ptr = PTFrame_GetResultPtr(work);
	RSLT_Setup( result_ptr );

	for( i=0;i<ENTRY_MEMBER_NUM_MAX;i++ ){
		int rec;
		rec = PTFrame_GetEvtResult(work, i);
		RSLT_SetResult(	work, result_ptr,
							i, rec,
							0, 3, msg_pkthln_new_record03 );
	}

	//ソート
	RSLT_Sort(result_ptr, SORT_REC_LARGE);
	//得点セット
	PTC_CalcPoint(result_ptr, PKTHLN_EVT_PUSH);

	//総得点に加算
	RSLT_AddTotalScore(result_ptr);

	//競技得点セット
	RSLT_SetEvtScore(result_ptr, PKTHLN_EVT_PUSH);

	return TRUE;
}


//--------------------------------------------------------------------------------------------
/**
 * 終了関数
 *
 * @param	work		ポケスロンワークポインタ
 * @param	*pParam		パラメータ
 *
 * @return	TRUE
 */
//--------------------------------------------------------------------------------------------
BOOL PE_PUSH_EndFunc(PKTHLN_PTR work, void *pParam)
{
	int i;
	PKTHLN_PUSH_PTR ptr = PTFrame_GetEventWorkPtr(work);

	// 通信アイコン撤去
	WirelessIconEasyEnd();

	//▼マーカ終了
	PTFrame_EndPosMarker(work);

	PtRing_End(ptr->RingCntPtr);

	//スクリーンアーカイブ解放
	sys_FreeMemoryEz(ptr->TimerBgArc);

	//BG削除
	GF_BGL_BGControlExit(ptr->bgl, GF_BGL_FRAME0_M );
	GF_BGL_BGControlExit(ptr->bgl, GF_BGL_FRAME1_M );
	GF_BGL_BGControlExit(ptr->bgl, GF_BGL_FRAME2_M );
	GF_BGL_BGControlExit(ptr->bgl, GF_BGL_FRAME3_M );
	GF_BGL_BGControlExit(ptr->bgl, GF_BGL_FRAME0_S );
	GF_BGL_BGControlExit(ptr->bgl, GF_BGL_FRAME1_S );
	GF_BGL_BGControlExit(ptr->bgl, GF_BGL_FRAME2_S );
	GF_BGL_BGControlExit(ptr->bgl, GF_BGL_FRAME3_S );

	//BMP
	GF_BGL_BmpWinDel( &ptr->Win );

	//BGL解放
	sys_FreeMemoryEz(ptr->bgl);

	//アクター解放
	PkthlnClAct_Free(ptr->ActCntPtr);

	//ポケアクターコントローラ解放
	PokeAct_Free(ptr->PokeActCntPtr);
	//共通リソースコントローラ解放
	CmnRes_Free(ptr->CmnResCntPtr);

	//OAMレンダラー破棄
	REND_OAM_Delete();

	DeleteCharManager();
	DeletePlttManager();

	//AIコントローラー解放
	PushAI_End(ptr->AICntPtr);
	//サブ画面コントローラー解放
	PushSub_Free(ptr->SubDispCntPtr);

	//タッチフォントアンロード
	FontProc_UnloadFont(FONT_TOUCH);

	sys_VBlankFuncChange( NULL, NULL );	// VBlankセット
	sys_HBlankIntrSet( NULL,NULL );		// HBlankセット

	//ソートバッファ解放
	sys_FreeMemoryEz(ptr->PokeSortBuf);

	//イベントワーク解放
	PTFrame_FreeEventWork(work);

	// 上下画面を元に戻しておく
	sys.disp3DSW = DISP_3D_TO_MAIN;
	GF_Disp_DispSelect();

	//特殊効果オフ
	G2_BlendNone();

	//ヒープ解放
	sys_DeleteHeap( HEAPID_PT_PUSH );

	return TRUE;
}

//--------------------------------------------------------------------------------------------
/**
 * VRAM設定		ポケスロンでは、ポケモン表示だけで0x30000必要となる。
 * VRAM_AB(0x40000)でないとはいらん
 *
 * @param	none
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void SetVramBank(void)
{
	GF_BGL_DISPVRAM tbl = {
		GX_VRAM_BG_64_E,				// メイン2DエンジンのBG
		GX_VRAM_BGEXTPLTT_NONE,			// メイン2DエンジンのBG拡張パレット

		GX_VRAM_SUB_BG_128_C,			// サブ2DエンジンのBG
		GX_VRAM_SUB_BGEXTPLTT_NONE,		// サブ2DエンジンのBG拡張パレット

		GX_VRAM_OBJ_256_AB,				// メイン2DエンジンのOBJ
		GX_VRAM_OBJEXTPLTT_NONE,		// メイン2DエンジンのOBJ拡張パレット

		GX_VRAM_SUB_OBJ_16_I,			// サブ2DエンジンのOBJ
		GX_VRAM_SUB_OBJEXTPLTT_NONE,	// サブ2DエンジンのOBJ拡張パレット

		GX_VRAM_TEX_NONE,				// テクスチャイメージスロット
		GX_VRAM_TEXPLTT_NONE			// テクスチャパレットスロット
	};
	GF_Disp_SetBank( &tbl );
}

//----------------------------------------------------------------------------
/**
 *	@brief	シーケンス関数
 *
 *	@param	work		ポケスロンポインタ
 *	@param	*seq		シーケンサ
 *
 *	@return	FALSE
 */
//-----------------------------------------------------------------------------
static BOOL PUSH_Func_Phase0(PKTHLN_PTR work, u8 *seq)
{
	BOOL rc;
	PKTHLN_PUSH_PTR ptr = PTFrame_GetEventWorkPtr(work);

	switch(*seq){
	case 0:
		//通信同期待ちセット
		PTFrame_SetSynchroID(work, PKTLN_SYNC_ID_PUSH_START_WAIT);
		(*seq)++;
		break;
	case 1:
		//みんな一緒にフェードインリクエスト
		WIPE_SYS_Start(	WIPE_PATTERN_FSAM, WIPE_TYPE_SHUTTERIN_DOWN,
						WIPE_TYPE_SHUTTERIN_DOWN, WIPE_FADE_BLACK,
						WIPE_DEF_DIV, WIPE_DEF_SYNC, ptr->HeapID );
		(*seq)++;
		break;
	case 2:
		//フェードイン待ち
		if( WIPE_SYS_EndCheck() ){
			//シーケンスシフト
			PTFrame_SetNextFuncTblIdx(work, PUSH_SEQ_PHASE1);
		}
	}

	return FALSE;
}


//----------------------------------------------------------------------------
/**
 *	@brief	シーケンス関数
 *
 *	@param	work		ポケスロンポインタ
 *	@param	*seq		シーケンサ
 *
 *	@return	FALSE
 */
//-----------------------------------------------------------------------------
static BOOL PUSH_Func_Phase1(PKTHLN_PTR work, u8 *seq)
{
	BOOL rc;
	PKTHLN_PUSH_PTR ptr = PTFrame_GetEventWorkPtr(work);

	switch(*seq){
	case 0:	//カウント
		if ( PTFrame_CountDown(work) ){
			(*seq)++;
		}
		break;
	case 1:
		CommMain(work);
		if ( ControlMain(work) ){
			(*seq)++;
		}
		break;
	case 2:
		//この競技はターン制のためここで親処理を呼ばなくても得点等にずれが起きない
		if ( PTFrame_DispEnd(work) ){
			//フェードアウトリクエスト
			WIPE_SYS_Start(	WIPE_PATTERN_WMS, WIPE_TYPE_FADEOUT,
							WIPE_TYPE_FADEOUT, WIPE_FADE_BLACK,
							WIPE_DEF_DIV, WIPE_DEF_SYNC, ptr->HeapID );
			//シーケンスシフト
			PTFrame_SetNextFuncTblIdx(work, PUSH_SEQ_PHASE2);
		}
	}


	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	シーケンス関数
 *
 *	@param	work		ポケスロンポインタ
 *	@param	*seq		シーケンサ
 *
 *	@return	TRUE
 */
//-----------------------------------------------------------------------------
static BOOL PUSH_Func_Phase2(PKTHLN_PTR work, u8 *seq)
{
	int point;
	int i,j;
	PKTHLN_PUSH_PTR ptr = PTFrame_GetEventWorkPtr(work);

	if (*seq == 0){
		//フェードアウト待ち
		if ( WIPE_SYS_EndCheck() ){
			*seq = 1;
		}
		return FALSE;
	}

	//結果はすべて親が管理しているので、子は処理をスルー
	if (PTFrameGetCurrentID(work) != COMM_PARENT_ID){
		return TRUE;
	}

	//結果セット
	for (i=0;i<ENTRY_MEMBER_NUM_MAX;i++){
		point = 0;
		for(j=0;j<ENTRY_MAX;j++){
			point += ptr->Poke[i][j].Score;
			PTFrame_SetEvtResultOrg(work, i, point);
		}
	}
	return TRUE;
}
//----------------------------------------------------------------------------
/**
 *	@brief	RECT_HIT_TBLを登録
 *
 *	@param	*rect		矩形データポインタ
 *	@param	x			X
 *	@param	y			Y
 *	@param	sizx		X幅
 *	@param	sizy		Y幅
 *
 *	@return none
 */
//-----------------------------------------------------------------------------
static void SetPokeRectHitTable(RECT_HIT_TBL *rect, int x, int y, int sizx, int sizy)
{
  rect->rect.top    = y - sizy / 2;
  rect->rect.left   = x - sizx / 2;
  rect->rect.bottom = y + sizy / 2;
  rect->rect.right  = x + sizx / 2;
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	BG初期化
 * @param	*ini		BGL
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void BgInit(GF_BGL_INI * ini)
{
	{	/* BG SYSTEM */
  	  GF_BGL_SYS_HEADER BGsys_data = {
    	  GX_DISPMODE_GRAPHICS, GX_BGMODE_0, GX_BGMODE_1, GX_BG0_AS_2D,
    	};
  	  GF_BGL_InitBG( &BGsys_data );
  	}

  	//メイン
  	{	/* MAIN DISP BG0 */
    	GF_BGL_BGCNT_HEADER MBg0_Data = {
	      0, 0, 0x800, 0,
    	  GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
		  GX_BG_SCRBASE_0xe800, GX_BG_CHARBASE_0x00000,		//ＢＧ0とＢＧ1はキャラを共通で使うのでベースが同じ
		  GX_BG_EXTPLTT_01, 3, 0, 0, FALSE
   	 };
   	 GF_BGL_BGControlSet( ini, GF_BGL_FRAME0_M, &MBg0_Data, GF_BGL_MODE_TEXT );
   	 GF_BGL_ScrClear( ini, GF_BGL_FRAME0_M );
 	}

	{	/* MAIN DISP BG1 */
  	  GF_BGL_BGCNT_HEADER MBg1_Data = {
    	  0, 0, 0x800, 0,
   	 	  GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
		  GX_BG_SCRBASE_0xf000, GX_BG_CHARBASE_0x00000,		//ＢＧ0とＢＧ1はキャラを共通で使うのでベースが同じ
		  GX_BG_EXTPLTT_01, 2, 0, 0, FALSE
   	 };
   	 GF_BGL_BGControlSet( ini, GF_BGL_FRAME1_M, &MBg1_Data, GF_BGL_MODE_TEXT );
   	 GF_BGL_ScrClear( ini, GF_BGL_FRAME1_M );
	}

	{	/* MAIN DISP BG2 */
  	  GF_BGL_BGCNT_HEADER MBg2_Data = {
    	  0, 0, 0x800, 0,
   	 	  GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
		  GX_BG_SCRBASE_0xe000, GX_BG_CHARBASE_0x04000,
    	  GX_BG_EXTPLTT_01, 0, 0, 0, FALSE
   	 };
   	 GF_BGL_BGControlSet( ini, GF_BGL_FRAME2_M, &MBg2_Data, GF_BGL_MODE_TEXT );
   	 GF_BGL_ScrClear( ini, GF_BGL_FRAME2_M );
	}

	{	/* MAIN DISP BG3 */
    	GF_BGL_BGCNT_HEADER MBg3_Data = {
	      0, 0, 0x800, 0,
    	  GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
		  GX_BG_SCRBASE_0xd800, GX_BG_CHARBASE_0x08000,
		  GX_BG_EXTPLTT_01, 0, 0, 0, FALSE
   	 };
   	 GF_BGL_BGControlSet( ini, GF_BGL_FRAME3_M, &MBg3_Data, GF_BGL_MODE_TEXT );
   	 GF_BGL_ScrClear( ini, GF_BGL_FRAME3_M );
 	}

	  //サブ
	{	/* SUB DISP BG0 */
 	   GF_BGL_BGCNT_HEADER SBg0_Data = {
    	  	0, 0, 0x800, 0,
   	  		GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
			GX_BG_SCRBASE_0xf800, GX_BG_CHARBASE_0x0c000,
    		GX_BG_EXTPLTT_01, 0, 0, 0, FALSE
  	  };
 	  GF_BGL_BGControlSet( ini, GF_BGL_FRAME0_S, &SBg0_Data, GF_BGL_MODE_TEXT );
  	  GF_BGL_ScrClear( ini, GF_BGL_FRAME0_S );
 	}

 	{	/* SUB DISP BG1 */
	    GF_BGL_BGCNT_HEADER SBg1_Data = {
    	  	0, 0, 0x800, 0,
 	  		GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
 	   		GX_BG_SCRBASE_0xf000, GX_BG_CHARBASE_0x08000,
  	   		GX_BG_EXTPLTT_01, 1, 0, 0, FALSE
		};
    	GF_BGL_BGControlSet( ini, GF_BGL_FRAME1_S, &SBg1_Data, GF_BGL_MODE_TEXT );
    	GF_BGL_ScrClear( ini, GF_BGL_FRAME1_S );
	}

	{	/* SUB DISP BG3 */
		GF_BGL_BGCNT_HEADER SBg3_Data = {
    		0, 0, 0x400, 0,
  		    GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_256,
		    GX_BG_SCRBASE_0xe800, GX_BG_CHARBASE_0x00000,
 		    GX_BG_EXTPLTT_01, 2, 0, 0, FALSE
		};
		GF_BGL_BGControlSet( ini, GF_BGL_FRAME3_S, &SBg3_Data, GF_BGL_MODE_AFFINE );
    	GF_BGL_ScrClear( ini, GF_BGL_FRAME3_S );
	}

	{	/* SUB DISP BG2 */
		GF_BGL_BGCNT_HEADER SBg2_Data = {
			0, 0, 0x800, 0,
		    GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
      		GX_BG_SCRBASE_0xe000, GX_BG_CHARBASE_0x08000,	//<<ベースが足らんので、FRAME1_Sと同じ場所指定
      		GX_BG_EXTPLTT_01, 3, 0, 0, FALSE
    	};
	    GF_BGL_BGControlSet( ini, GF_BGL_FRAME2_S, &SBg2_Data, GF_BGL_MODE_TEXT );
  	  	GF_BGL_ScrClear( ini, GF_BGL_FRAME2_S );
 	 }

	//レコードＢＧ非表示
	GF_Disp_GX_VisibleControl( GX_PLANEMASK_BG3, VISIBLE_OFF );
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	グラフィックセット
 * @param	ptr			アプリポインタ
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void SetGraphic(PKTHLN_PUSH_PTR ptr)
{
	//メインキャラ
	ArcUtil_BgCharSet(ARC_PKTHEV_PUSH, NARC_pkthev_push_push_bg_main_ncgr,
						ptr->bgl, GF_BGL_FRAME0_M, 0, 0, FALSE, ptr->HeapID);
	//READYキャラ
	ArcUtil_BgCharSet(ARC_PKTHEV_PUSH, NARC_pkthev_push_push_bg_main_ready_ncgr,
						ptr->bgl, GF_BGL_FRAME2_M, 0, 0, FALSE, ptr->HeapID);

	//サブキャラ
	ArcUtil_BgCharSet(ARC_PKTHEV_PUSH, NARC_pkthev_push_push_bg_sub01_ncgr,
						ptr->bgl, GF_BGL_FRAME1_S, 0, SUB_WIDE_SCREEN_CHAR_SIZE*32, FALSE, ptr->HeapID);
	ArcUtil_BgCharSet(ARC_PKTHEV_PUSH, NARC_pkthev_push_push_bg_sub02_logo_ncgr,
						ptr->bgl, GF_BGL_FRAME3_S, 0, 0, FALSE, ptr->HeapID);
	ArcUtil_BgCharSet(ARC_PKTHEV_PUSH, NARC_pkthev_push_push_bg_sub02_ncgr,
						ptr->bgl, GF_BGL_FRAME2_S, SUB_WIDE_SCREEN_CHAR_SIZE, 0, FALSE, ptr->HeapID);
	//↑32*4のオフセットをつけて、GF_BGL_FRAME1_Sで使用するキャラの後ろに展開する

	//土台スクリーン
	ArcUtil_ScrnSet(ARC_PKTHEV_PUSH, NARC_pkthev_push_push_bg_main_nscr,
						ptr->bgl, GF_BGL_FRAME0_M, 0, 0, FALSE, ptr->HeapID);
	//READYスクリーン
	{
		void *arc;
		NNSG2dScreenData *scr_data;
		arc = ArcUtil_ScrnDataGet(ARC_PKTHEV_PUSH, NARC_pkthev_push_push_bg_main_ready_nscr,
						FALSE, &scr_data, ptr->HeapID);
		GF_BGL_ScreenBufSet( ptr->bgl, GF_BGL_FRAME2_M, scr_data->rawData, scr_data->szByte );
		GF_BGL_ScrPalChange( ptr->bgl, GF_BGL_FRAME2_M, 0, 0, 32, 24, 1 );
		GF_BGL_LoadScreenV_Req(ptr->bgl, GF_BGL_FRAME2_M);
		sys_FreeMemoryEz(arc);
	}

	//タイマースクリーン
	ptr->TimerBgArc = ArcUtil_ScrnDataGet(ARC_PKTHEV_PUSH, NARC_pkthev_push_push_bg_main_light_nscr,
						FALSE, &ptr->TimerScrnData, ptr->HeapID);
	GF_BGL_ScreenBufSet( ptr->bgl, GF_BGL_FRAME1_M, ptr->TimerScrnData->rawData, ptr->TimerScrnData->szByte );
	GF_BGL_LoadScreen( ptr->bgl, GF_BGL_FRAME1_M, ptr->TimerScrnData->rawData, ptr->TimerScrnData->szByte, 0 );

	//サブスクリーン
	PushSub_SetScreen(ptr->SubDispCntPtr);

	//メインパレット
	ArcUtil_PalSet( ARC_PKTHEV_PUSH, NARC_pkthev_push_push_bg_main_nclr,
						PALTYPE_MAIN_BG, 0, 32, ptr->HeapID );
	ArcUtil_PalSet( ARC_PKTHEV_PUSH, NARC_pkthev_push_push_bg_main_ready_nclr,
						PALTYPE_MAIN_BG, 32, 32, ptr->HeapID );
	//サブパレット
	ArcUtil_PalSet( ARC_PKTHEV_PUSH, NARC_pkthev_push_push_bg_sub02_logo_nclr,
						PALTYPE_SUB_BG, 0, 64, ptr->HeapID );
	ArcUtil_PalSet( ARC_PKTHEV_PUSH, NARC_pkthev_push_push_bg_sub01_nclr,
						PALTYPE_SUB_BG, 64, 32, ptr->HeapID );
	ArcUtil_PalSet( ARC_PKTHEV_PUSH, NARC_pkthev_push_push_bg_sub02_nclr,
						PALTYPE_SUB_BG, 96, 32, ptr->HeapID );

	//ＲＥＡＤＹ表示オフセット
	G2_SetBG2Offset(0, READY_BG_START_OFS);
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	通信データセット
 * @param	ptr		ポケスロンアプリポインタ
 * @param	parent	親データ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void SetCommInfo(PKTHLN_PUSH_PTR ptr, PUSH_PARENT_DATA *parent)
{
	u8 i;

	int data,st,st2;
	u8 header,total_score;
	data = 0;
	st = 0;
	st2 = 0;

	for(i=0;i<PUSH_EVENT_POKE_NUM;i++){
		int x,y;
		int dir;
		u8 state;
		PUSH_POKE *push_poke;
		push_poke = &ptr->Poke[i/ENTRY_MAX][i%ENTRY_MAX];
		x = (push_poke->NowPoint.x/FX32_ONE);
		y = (push_poke->NowPoint.y/FX32_ONE);

		//表示リミッター処理(これがないと、回り込みが発生してしまう)
		if (x<0){
			x = 0;
		}else if(x>255){
			x = 255;
		}
		if (y<0){
			y = 0;
		}else if(y>255){
			y = 255;
		}
		state  = push_poke->State;
		dir = push_poke->Dir - 1;		//0〜3の値に収める
///		OS_Printf("%d::%x,%x,%d,%d\n",i, x,y,dir,state);
		//データ格納
		parent->PokeX[i] = x;
		parent->PokeY[i] = y;

		data += ( dir<<(i*2) );
		st += (state<<(i*2));
		st2 += (push_poke->Fatigue << i);
	}
	parent->Dir = data;
	parent->Dir += (ptr->CommTime << (PUSH_EVENT_POKE_NUM*2));

	parent->PokeSt = 0;
	parent->PokeSt += st;
	parent->PokeSt += (ptr->ParentFieldType <<(PUSH_EVENT_POKE_NUM*2));
	parent->PokeSt += (ptr->SendPointUpPokeIdx << 28);

	//今回送る合計得点データを決定
	{
		header = ptr->SendNetID;
		total_score = ptr->TotalScore[ptr->SendNetID];
		ptr->SendNetID = (ptr->SendNetID+1)%ENTRY_MEMBER_NUM_MAX;
	}

	parent->PokeSt2 = 0;
	parent->PokeSt2 += st2;
	parent->PokeSt2 += ptr->EndFlg << PUSH_EVENT_POKE_NUM;
	parent->PokeSt2 += (ptr->CalcScoreCall<<(1+PUSH_EVENT_POKE_NUM));
	parent->PokeSt2 += (ptr->GamePause<<(2+PUSH_EVENT_POKE_NUM));
	parent->PokeSt2 += (ptr->SendPointNo<<(3+PUSH_EVENT_POKE_NUM));
	parent->PokeSt2 += (total_score<<(6+PUSH_EVENT_POKE_NUM));
	parent->PokeSt2 += (header<<(14+PUSH_EVENT_POKE_NUM));
	parent->PokeSt2 += (ptr->FieldCount<<(28));

	ptr->CalcScoreCall = 0;
	ptr->SendPointUpPokeIdx = PUSH_EVENT_POKE_NUM;
	ptr->SendPointNo = 0;
}


//----------------------------------------------------------------------------
/**
 *	@brief		メイン関数
 *
 *	@param	work	ポケスロンポインタ
 *
 *	@return	終了でTRUE
 */
//-----------------------------------------------------------------------------
static BOOL ControlMain(PKTHLN_PTR work)
{
	PKTHLN_PUSH_PTR ptr = PTFrame_GetEventWorkPtr(work);

	PUSH_CHILD_DATA *child_data;
	COMM_EVENT_COMMON_DATA *data;
	data = PTFrame_GetEvtComCmnData(work);
	child_data = PKTHLN_CommPack_GetData(&data->SendData);
	child_data->TouchValid = FALSE;

	//終了検出
	{
		u8 end;
		PUSH_PARENT_DATA *parent;
		parent = PKTHLN_CommPack_GetData(&data->ReciveShareData);
		end = (parent->PokeSt2 >> PUSH_EVENT_POKE_NUM) & 0x1;	//1ビットマスク
#ifdef PM_DEBUG
		if (sys.trg & PAD_BUTTON_X){
			end = 1;
		}
#endif
		if (end){
			//アクター停止
			PkthlnClAct_AllAnmStop(ptr->ActCntPtr, 1);
			PokeAct_AllAnmStop(ptr->PokeActCntPtr, 1);
			PTFrame_StopPosMarker(work);
			//ニューレコード用にレコードをセット
			{
				u8 point;
				point = PushSub_GetDispScore(ptr->SubDispCntPtr);
				//フレームワークにニューレコードチェック用のレコード値をセット
				PTFrame_SetCheckRecord(work, point);
				SetRecordStr(ptr, point);
			}
			return TRUE;
		}

/**
#ifdef PM_DEBUG
		//自爆機能
		if ( sys.trg & PAD_KEY_LEFT ){
			int i;
			for(i=0;i<ENTRY_MAX;i++){
				push_poke *push_poke = &ptr->Poke[0][i];
				if (push_poke->State == POKE_ALIVE){
					//ポケモン気絶
					push_poke->State = POKE_NONE;
					//現在タイムを保存
					push_poke->Time = ptr->Time;
				}
			}
		}
		if ( sys.trg & PAD_KEY_UP ){
			int i;
			for(i=0;i<ENTRY_MAX;i++){
				push_poke *push_poke = &ptr->Poke[1][i];
				if (push_poke->State == POKE_ALIVE){
					//ポケモン気絶
					push_poke->State = POKE_NONE;
					//現在タイムを保存
					push_poke->Time = ptr->Time;
				}
			}
		}
#endif
*/
	}

	//フィールド展開
	if (ptr->FldChgReq){
		FIELD_LEVEL level;
		if (ptr->FieldCount<FRAME_COUNT_LV1){
			level = FIELD_LEVEL1;
		}else if(ptr->FieldCount<FRAME_COUNT_LV2){
			level = FIELD_LEVEL2;
		}else if(ptr->FieldCount<FRAME_COUNT_LV3){
			level = FIELD_LEVEL3;
		}else{
			level = FIELD_LEVEL4;
		}
		ptr->ParentFieldType = PtRing_GetNextFieldType(ptr->ParentFieldType, level);
		ptr->FldChgReq = 0;
	}

	//タッチ座標検出
	if (GF_TP_GetTrg()){
		//アクションポイント加算「タッチ回数」
		PTFrame_AddActionPoint(	work, PTFrameGetCurrentID(work), ENTRY_MAX, ADD_TYPE_TOUCH, 1 );
	}
	if (GF_TP_GetCont()){
		//通信データに座標をセット
		child_data->TpX = sys.tp_x;
		child_data->TpY = sys.tp_y;
		child_data->TouchValid = TRUE;
	}

	SetDraw(work);

	return FALSE;
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	通信データ関連メイン処理
 * @param	work		ポケスロンアプリポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void CommMain(PKTHLN_PTR work)
{
	int i;
	PKTHLN_PUSH_PTR ptr;
	PUSH_CHILD_DATA *child_data;
	PUSH_PARENT_DATA *parent;
	COMM_EVENT_COMMON_DATA *data;
	data = PTFrame_GetEvtComCmnData(work);
	ptr = PTFrame_GetEventWorkPtr(work);

	//親動作
	if ( PTFrameGetCurrentID(work) == COMM_PARENT_ID ){

		parent = PKTHLN_CommPack_GetData(&data->SendShareData);

		//子機からのローカルエフェクト終了待ち
		if (ptr->LocalWait == TRUE){
			u8 num = 0;
			u8 max = PTFrame_GetPlayerNum(work);
			for(i=0;i<max;i++){
				PUSH_CHILD_DATA *child_data;
				child_data = PKTHLN_CommPack_GetData(&data->ReciveData[i]);
				if (child_data->LocalEnd){
					num++;
				}
			}
			if (num == max){
				OS_Printf("全員から通達\n");
				ptr->CommTime = 0;
				//ポーズ解除
				ptr->GamePause = 0;
				ptr->LocalWait = FALSE;
			}
		}else if (ptr->Interval > 0){	//時間経過
			ptr->Interval--;
			if (ptr->Interval == 0){
				ptr->LocalWait = TRUE;
			}else if (ptr->Interval == INTERVAL_FLD_DISP_START){
				//フィールド変更リクエスト
				ptr->FldChgReq = 1;
				ptr->FieldCount++;
#ifdef PM_DEBUG
				if (DebugPkthlnWk.TimeInfinity){
					if (ptr->FieldCount >= FIELD_COUNT_MAX){
						ptr->FieldCount--;
					}
				}
#endif
			}
		}else{
			if (ptr->GamePause){
				ptr->CommTime = ONE_CYCLE_TIME+1;	//ポーズ中の特別値
				if (ptr->CalcScoreCallWait == 0){
					if (ptr->PointUpWait==0){
						//ポイント加算されるポケを全部表示したか？
						if ( ptr->PointUpNum >= ptr->PointUpNumMax ){	//表示した
							//ポケ復活処理
							RevivePoke(ptr);
							//インターバルへ
							ptr->Interval = INTERVAL_TIME;
						}else{		//表示してない
							u8 team;
							//ポイント表示するポケモンのインデックスをセット
							ptr->SendPointUpPokeIdx = ptr->PointUpList[ptr->PointUpNum];
							ptr->SendPointNo = PtRing_ChangeToNo(ptr->PointList[ptr->PointUpNum]);
							//送りつける合計得点に加算
							team = ptr->SendPointUpPokeIdx/ENTRY_MAX;
							ptr->TotalScore[team] += ptr->PointList[ptr->PointUpNum];
							ptr->PointUpNum++;
							//ウェイトセット
							ptr->PointUpWait = POINT_UP_WAIT;
							//アクションポイント加算「得点回数」
							PTFrame_AddActionPoint(	work, team, ptr->SendPointUpPokeIdx%ENTRY_MAX, ADD_TYPE_GET, 1 );
						}
					}else{
						ptr->PointUpWait--;
					}
				}else{
					ptr->CalcScoreCallWait--;//コールウェイト消化
				}
			}else{
				int sync_max;
				//ラウンドにより最大シンク決定
				if ( ptr->FieldCount<FRAME_COUNT_LV1 ){
					sync_max = COUNT_UP_SYNC_LV1;
				}else if ( ptr->FieldCount<FRAME_COUNT_LV2 ){
					sync_max = COUNT_UP_SYNC_LV2;
				}else{
					sync_max = COUNT_UP_SYNC_LV3;
				}
				ptr->Sync++;
				if (ptr->Sync >= sync_max){
					ptr->Sync = 0;
					ptr->CommTime++;
					if (ptr->CommTime >= ONE_CYCLE_TIME){
						//得点加算リクエスト
						ptr->AddScoreReq = 1;
						//ポーズ開始コール
						ptr->CalcScoreCall = 1;
						//ゲームポーズ
						ptr->GamePause = 1;
						//コールウェイトセット
						ptr->CalcScoreCallWait = CALC_SCR_CALL_WAIT;
						//全員の入力状態等を完全にクリア
						{
							//ホールド状態クリア
							for(i=0;i<ENTRY_MEMBER_NUM_MAX;i++){
								ptr->HoldPokeNo[i] = PUSH_EVENT_POKE_NUM;
							}
							//推進力クリア・プラスパワーのクリア
							for(i=0;i<PUSH_EVENT_POKE_NUM;i++){
								PUSH_POKE *push_poke;
								push_poke = &ptr->Poke[i/ENTRY_MAX][i%ENTRY_MAX];
								push_poke->LastPoint = push_poke->NowPoint;
								push_poke->MoveVec.x = 0;
								push_poke->MoveVec.y = 0;
								//スタミナ関連
								push_poke->Param.StaminaNow = push_poke->Param.StaminaMax;
								push_poke->Fatigue = 0;
								push_poke->FatCount = 0;
								//パワークリア
								push_poke->PlusPower = 0;
								push_poke->PowerLifeTime = 0;
							}
						}
					}
				}
			}
		}

		//終了判定
		if ( ptr->FieldCount >= FIELD_COUNT_MAX ){
			ptr->EndFlg = 1;		//終了フラグ
		}else{
			ptr->EndFlg = 0;
		}


		//親データは直接レシーバにセット
		{
			PUSH_CHILD_DATA *child;
			PUSH_CHILD_DATA *child_rec;

			child_rec = PKTHLN_CommPack_GetData(&data->ReciveData[0]);
			child = PKTHLN_CommPack_GetData(&data->SendData);
			(*child_rec) = (*child);
		}

		if (!ptr->GamePause){
			//プレーヤー数ループ
			for(i=0;i<ENTRY_MEMBER_NUM_MAX;i++){
				PUSH_CHILD_DATA *child_data;
				PUSH_POKE *push_poke;
				child_data = PKTHLN_CommPack_GetData(&data->ReciveData[i]);
				//タッチ状況を整理
				if (child_data->TouchValid){
					if ( (ptr->TpState[i].Trg)&&(ptr->TpState[i].Cont) ){
						ptr->TpState[i].Trg = FALSE;
					}else if((!ptr->TpState[i].Trg)&&(!ptr->TpState[i].Cont)){
						ptr->TpState[i].Trg = TRUE;
						ptr->TpState[i].Cont = TRUE;
					}
				}else{
					ptr->TpState[i].Trg = FALSE;
					ptr->TpState[i].Cont = FALSE;
				}

				if (ptr->TpState[i].Trg){
					//自分のポケが全リタしているかで分岐
					if ( !IsRetire(ptr, i) ){
						//まだ生存中
						u8 poke_no;
						//自分のポケモンをタッチしたかを検出
						poke_no = CheckPokeTouch(ptr, i, child_data->TpX, child_data->TpY);
						//自分のポケか？
						if ( (poke_no != PUSH_EVENT_POKE_NUM) ){
							push_poke = &ptr->Poke[i][poke_no%ENTRY_MAX];
							//ホールド登録
							ptr->HoldPokeNo[i] = poke_no;
							//プラスパワーセット
							push_poke->PlusPower = PLUS_POWER;
							push_poke->PowerLifeTime = PLUS_POWER_LIFE_TIME;
						}
					}
				}else if (ptr->TpState[i].Cont){ //最終到達地点の上書き
					u8 poke_idx;
					//ホールドポケいなければ、処理しない
					if (ptr->HoldPokeNo[i] == PUSH_EVENT_POKE_NUM){
						continue;
					}
					poke_idx = ptr->HoldPokeNo[i]%ENTRY_MAX;
					push_poke = &ptr->Poke[i][poke_idx];

					//目的ポイントの算出
					GetLastPoint(child_data->TpX, child_data->TpY, &push_poke->NowPoint, 0/*push_poke->Range*/, &push_poke->LastPoint);
					//ポケのラストポイントが場外かを判定する
					if ( CheckFldOutRange(push_poke->PokeActPtr,
									push_poke->LastPoint.x, push_poke->LastPoint.y) ){
						//自滅予約
						ptr->Suicide[ ptr->HoldPokeNo[i] ] = 1;
					}else{
						ptr->Suicide[ ptr->HoldPokeNo[i] ] = 0;
					}
				}else{	//タッチしていない
					if ( ptr->HoldPokeNo[i] != PUSH_EVENT_POKE_NUM ){
						u8 poke_idx = ptr->HoldPokeNo[i]%ENTRY_MAX;
						push_poke = &ptr->Poke[i][poke_idx];
						//ホールド解除
						ptr->HoldPokeNo[i] = PUSH_EVENT_POKE_NUM;
					}
				}
			}	//end for(i=0;i<ENTRY_MEMBER_NUM_MAX;i++)
			//AI実行
			{
				PUSH_POKE *ai_poke;
				u8 exe_idx = PUSH_EVENT_POKE_NUM;
#ifdef PM_DEBUG										//こっちデバッグ用
				if ( !DebugPkthlnWk.AI_Stop ){
					exe_idx = PushAI_Execute(ptr->AICntPtr, ptr->ParentFieldType);
				}
#else												//こっち製品用
				exe_idx = PushAI_Execute(ptr->AICntPtr, ptr->ParentFieldType);
#endif
				//ＡＩプラスパワーセット
				if (exe_idx != PUSH_EVENT_POKE_NUM){
					u8 npc_idx;
					npc_idx = exe_idx/ENTRY_MAX;
					if(npc_idx >= PTFrame_GetPlayerNum(work)){
						ai_poke = &ptr->Poke[npc_idx][exe_idx%ENTRY_MAX];
						ai_poke->PlusPower = PLUS_POWER;
						ai_poke->PowerLifeTime = PLUS_POWER_LIFE_TIME;
					}else{
						OS_Printf("AI_IDX_ERROR:%d  PLAYER_NUM\n",exe_idx, PTFrame_GetPlayerNum(work));
						GF_ASSERT(0);
					}
				}
			}
		}

		//ポケモンの移動
		MovePoke(work);
		//コネクトデータ作成
		MakeConectData(ptr);
		//得点チェック
		CheckScore(ptr);

		//情報セット
		SetCommInfo(ptr, parent);
#if 0
		{
			int data,st,st2;
			u8 header,total_score;
			data = 0;
			st = 0;
			st2 = 0;

			for(i=0;i<PUSH_EVENT_POKE_NUM;i++){
				int x,y;
				int dir;
				u8 state;
				PUSH_POKE *push_poke;
				push_poke = &ptr->Poke[i/ENTRY_MAX][i%ENTRY_MAX];
				x = (push_poke->NowPoint.x/FX32_ONE);
				y = (push_poke->NowPoint.y/FX32_ONE);
				//表示リミッター処理(これがないと、回り込みが発生してしまう)
				if (x<0){
					x = 0;
				}else if(x>255){
					x = 255;
				}
				if (y<0){
					y = 0;
				}else if(y>255){
					y = 255;
				}
				state  = push_poke->State;
				dir = push_poke->Dir - 1;		//0〜3の値に収める
///				OS_Printf("%d::%x,%x,%d,%d\n",i, x,y,dir,state);
				//データ格納
				parent->PokeX[i] = x;
				parent->PokeY[i] = y;

				data += ( dir<<(i*2) );
				st += (state<<(i*2));
				st2 += (push_poke->Fatigue << i);
			}
			parent->Dir = data;
			parent->Dir += (ptr->CommTime << (PUSH_EVENT_POKE_NUM*2));

			parent->PokeSt = 0;
			parent->PokeSt += st;
			parent->PokeSt += (ptr->ParentFieldType <<(PUSH_EVENT_POKE_NUM*2));
			parent->PokeSt += (ptr->SendPointUpPokeIdx << 28);

			//今回送る合計得点データを決定
			{
				header = ptr->SendNetID;
				total_score = ptr->TotalScore[ptr->SendNetID];

				ptr->SendNetID = (ptr->SendNetID+1)%ENTRY_MEMBER_NUM_MAX;
			}

			parent->PokeSt2 = 0;
			parent->PokeSt2 += st2;
			parent->PokeSt2 += ptr->EndFlg << PUSH_EVENT_POKE_NUM;
			parent->PokeSt2 += (ptr->CalcScoreCall<<(1+PUSH_EVENT_POKE_NUM));
			parent->PokeSt2 += (ptr->GamePause<<(2+PUSH_EVENT_POKE_NUM));
			parent->PokeSt2 += (ptr->SendPointNo<<(3+PUSH_EVENT_POKE_NUM));
			parent->PokeSt2 += (total_score<<(6+PUSH_EVENT_POKE_NUM));
			parent->PokeSt2 += (header<<(14+PUSH_EVENT_POKE_NUM));
			parent->PokeSt2 += (ptr->FieldCount<<(28));

			ptr->CalcScoreCall = 0;
			ptr->SendPointUpPokeIdx = PUSH_EVENT_POKE_NUM;
			ptr->SendPointNo = 0;
		}
#endif
	}
}

//----------------------------------------------------------------------------
/**
 *	@brief		描画座標関連セット関数
 *
 *	@param	work	ポケスロンポインタ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void SetDraw(PKTHLN_PTR work)
{
	int i;
	int draw_x,draw_y;
	int score;
	int field;
	u8 time;
	u8 pause_call;
	u8 pause;
	u8 get_score_no;
	u8 net_id;
	u8 total_score;
	u8 round;

	u8 fall_list[PUSH_EVENT_POKE_NUM];

	u8 my_net_id;

	PUSH_CHILD_DATA *child_data;

	COMM_EVENT_COMMON_DATA * data;
	PUSH_PARENT_DATA *parent;
	PKTHLN_PUSH_PTR ptr = PTFrame_GetEventWorkPtr(work);

	data = PTFrame_GetEvtComCmnData(work);
	parent = PKTHLN_CommPack_GetData(&data->ReciveShareData);

	my_net_id = PTFrameGetCurrentID(work);

	score = (parent->PokeSt >> 28) & 0xf;	//4ビットマスク
	field = (parent->PokeSt >> (PUSH_EVENT_POKE_NUM*2)) & 0xf;	//4ビットマスク
	time = (parent->Dir >> (PUSH_EVENT_POKE_NUM*2)) & 0xff;	//8ビットマスク
	pause_call = (parent->PokeSt2>>(1+PUSH_EVENT_POKE_NUM)) & 0x1;	//1ビットマスク
	pause = (parent->PokeSt2>>(2+PUSH_EVENT_POKE_NUM)) & 0x1;	//1ビットマスク
	get_score_no = (parent->PokeSt2>>(3+PUSH_EVENT_POKE_NUM)) & 0x7;	//3ビットマスク
	net_id = (parent->PokeSt2>>(14+PUSH_EVENT_POKE_NUM)) & 0x3;	//2ビットマスク
	total_score = (parent->PokeSt2>>(6+PUSH_EVENT_POKE_NUM)) & 0xff;	//8ビットマスク
	round = (parent->PokeSt2>>28) & 0xf;	//4ビットマスク
	round+=1;

	if (!pause){
		COMM_EVENT_COMMON_DATA *data;
		data = PTFrame_GetEvtComCmnData(work);
		child_data = PKTHLN_CommPack_GetData(&data->SendData);
		//子機送信データにローカル処理終了状態フラグを0セット
		child_data->LocalEnd = 0;
	}

	//フィールド表示
	{
		u8 old,new;
		old = ptr->NowFieldType;
		new = field;
///		OS_Printf("old_new:%d,%d",old,new);
		if (old != new){
			ptr->NowFieldType = new;
/**
			PtRing_MakeField(ptr->RingCntPtr, ptr->NowFieldType);
			PtRing_ClearData(ptr->RingCntPtr, old);
*/
			//グレースケールフラグをすべて落とす
			for(i=0;i<PUSH_EVENT_POKE_NUM;i++){
				ptr->GrayScale[i] = 0;
			}
			//ローカルエフェクト開始
			SetLocalEff(&ptr->LocalEff, old, new, work);
		}
	}

	//時間
	if ( time == 0 ){
		GF_BGL_ScreenBufSet( ptr->bgl, GF_BGL_FRAME1_M, ptr->TimerScrnData->rawData, ptr->TimerScrnData->szByte );
		GF_BGL_LoadScreenV_Req(ptr->bgl, GF_BGL_FRAME1_M);
		ptr->RestThreeSec = 0;
	}else if(time < ONE_CYCLE_TIME){
		if( (!ptr->RestThreeSec) ){
			//残り約3秒音
			if ( (round <= FRAME_COUNT_LV1) &&
					(time >= ONE_CYCLE_TIME-(SE_REST_TIME / COUNT_UP_SYNC_LV1)) ){
				Snd_SePlay( SE_PUSH_COUNT );
				ptr->RestThreeSec = 1;
			}else if( (FRAME_COUNT_LV1 < round ) &&
					(time >= ONE_CYCLE_TIME-(SE_REST_TIME / COUNT_UP_SYNC_LV2)) ){
				Snd_SePlay( SE_PUSH_COUNT );
				ptr->RestThreeSec = 1;
			}else if ( (FRAME_COUNT_LV2 < round )&&
					(time >= ONE_CYCLE_TIME-(SE_REST_TIME / COUNT_UP_SYNC_LV3)) ){
				Snd_SePlay( SE_PUSH_COUNT );
				ptr->RestThreeSec = 1;
			}
		}
		FillTimerBG(time, ptr->bgl);
	}else{
		u16 data[8] = {
			290, 291, 292, 293,
			322, 323, 324, 325
		};
		GF_BGL_ScrWrite( ptr->bgl, GF_BGL_FRAME1_M, data, 14, 2, 4, 2 );
		FillTimerBG(ONE_CYCLE_TIME-1, ptr->bgl);
	}

	//効果音
	if (pause_call){
		Snd_SePlay( SE_PUSH_SCORE_ON );
	}

	//ラウンド
	PushSub_UpdateRoundDisp(ptr->SubDispCntPtr, round);
/**
	{
		OS_Printf("player:%d==SCORE:%d\n",net_id, total_score);
	}
*/
	for (i=0;i<PUSH_EVENT_POKE_NUM;i++){
		int x,y;
		u8 dir;
		u8 state;
		u8 fatigue;
		PUSH_POKE *push_poke;
		CLACT_WORK_PTR clact_ptr;
		PCLACT_PTR	pclact_ptr;
		push_poke = &ptr->Poke[i/ENTRY_MAX][i%ENTRY_MAX];
		pclact_ptr = PokeAct_GetPclActPtr(push_poke->PokeActPtr);
		clact_ptr = PCLACT_GetClActWorkPtr(pclact_ptr);

		state = (parent->PokeSt >> (i*2)) & 0x3;	//2ビットマスク
		fatigue = (parent->PokeSt2 >> i) & 0x1;	//1ビットマスク

		//ポケ気絶チェック
		if (state == POKE_NONE){
			int fall_y_ofs;
			fall_y_ofs = 0;	//落下オフセットクリア
			//ローカルアニメフラグ開始してるかで分岐
			if ( ptr->OutLclAnm[i].AnmSeq == 0 ){		//アニメしてない
				//ローカルアニメ開始
				ptr->OutLclAnm[i].AnmSeq = 1;
			}else if (ptr->OutLclAnm[i].AnmSeq == 1){		//アニメしてる
				VecFx32 scale;
				u16 rot;
				float val[6] = {1.0, 0.9, 0.8, 0.7, 0.6, 0.5};
				int fall_y_ofs_tbl[6] = {0, 2, 6, 10, 14, 16};
				scale.x = val[ptr->OutLclAnm[i].AnmFrame/2] * FX32_ONE;
				scale.y = val[ptr->OutLclAnm[i].AnmFrame/2] * FX32_ONE;
				scale.z = val[ptr->OutLclAnm[i].AnmFrame/2] * FX32_ONE;
				//底辺で落下した場合はＹオフセットをつける
				{
					int sx,sy;
					PokeAct_GetShadowPosByTouchPos(push_poke->PokeActPtr, parent->PokeX[i], parent->PokeY[i], &sx, &sy);
					if (sy >= HEIGHT_MAX){
						fall_y_ofs = fall_y_ofs_tbl[ptr->OutLclAnm[i].AnmFrame/2];
					}
				}

				//フレーム更新
				ptr->OutLclAnm[i].AnmFrame++;
				//アフィンセット
				PokeAct_SetAffine(push_poke->PokeActPtr, CLACT_AFFINE_NORMAL);

				//スケールセット
				CLACT_SetScale(clact_ptr, &scale);
				if (ptr->OutLclAnm[i].AnmFrame >= 12){
					ptr->OutLclAnm[i].AnmSeq = 2;
				}

			}else {
				//ポケモンをバニッシュ
				PokeAct_DispCnt(push_poke->PokeActPtr, FALSE);
			}

			//汗バニッシュ
			PkthlnClAct_SetActive(push_poke->SweatActPtr, TRUE, FALSE);
			//影バニッシュ
			PokeAct_ShdwDispCnt(push_poke->PokeActPtr, 0);
			//ポケ描画
			{
				int draw_x = parent->PokeX[i];
				int draw_y = parent->PokeY[i]+fall_y_ofs;
				PokeAct_SetPosTouch(push_poke->PokeActPtr, draw_x, draw_y, TRUE);
			}
			fall_list[i] = 1;

			continue;
		}else{
			VecFx32 scale;
			ptr->OutLclAnm[i].AnmSeq = 0;
			ptr->OutLclAnm[i].AnmFrame = 0;

			//フレーム更新
			scale.x = 1.0 * FX32_ONE;
			scale.y = 1.0 * FX32_ONE;
			scale.z = 1.0 * FX32_ONE;

			//アフィンセット
			PokeAct_SetAffine(push_poke->PokeActPtr, CLACT_AFFINE_NONE);

			//疲労中
			if (fatigue){
///				OS_Printf("%d:疲労状態\n",i);
				PkthlnClAct_SetActive(push_poke->SweatActPtr, TRUE, TRUE);
				//自分のポケならＳＥ鳴らす
				if (i/ENTRY_MAX == my_net_id){
					if( Snd_SePlayCheck(SE_THLON_RUNNING_OUT) == FALSE ){	//再生終了していたら
						Snd_SePlay( SE_THLON_RUNNING_OUT );					//疲労音
					}
				}
			}else{
				PkthlnClAct_SetActive(push_poke->SweatActPtr, TRUE, FALSE);
			}

			//スケールセット
			CLACT_SetScale(clact_ptr, &scale);

			//ポケモンを表示
			PokeAct_DispCnt(push_poke->PokeActPtr, TRUE);

			if ( (state==POKE_REVIVE)&&(ptr->GrayScale[i]==0) ){	//復活状態で、グレースケールパレット転送していない
				ptr->GrayScale[i] = 1;
				//グレースケールパレット転送
				PokeAct_ChangePalette(ptr->PokeActCntPtr, i, NNS_G2D_VRAM_TYPE_2DMAIN, push_poke->MonsPal[1] );
			}else if( (state==POKE_ALIVE)&&(ptr->GrayScale[i]==1) ){	//生存状態で、通常パレット転送していない
				ptr->GrayScale[i] = 0;
				//通常パレット転送
				PokeAct_ChangePalette(ptr->PokeActCntPtr, i, NNS_G2D_VRAM_TYPE_2DMAIN, push_poke->MonsPal[0] );
			}

			fall_list[i] = 0;
		}

		x = parent->PokeX[i];
		y = parent->PokeY[i];
		dir = ( (parent->Dir >> (i*2)) & 0x3 );	//2ビットマスク
		dir += 1;	//1〜4の値に復元
		//描画座標計算
		draw_x = x;
		draw_y = y;

///		OS_Printf("%d::通信で受け取ったデータ%d\n",i,dir);

		push_poke = &ptr->Poke[i/ENTRY_MAX][i%ENTRY_MAX];
		push_poke->Pos.x = draw_x * FX32_ONE;
		push_poke->Pos.y = draw_y * FX32_ONE;

		//ポイント
		{
			CLACT_WORK_PTR act_ptr;
			VecFx32 mat = {0,0,0};
			mat.x = push_poke->Pos.x;
			mat.y = push_poke->Pos.y;
			act_ptr = PkthlnClAct_GetClActWorkPtr(push_poke->PointActPtr);
			CLACT_SetMatrix(act_ptr, &mat);
		}

		//汗
		{
			CLACT_WORK_PTR act_ptr;
			VecFx32 mat = {0,0,0};
			const PKTHPOKE_PARAM * prm;

			mat.x = push_poke->Pos.x;
			mat.y = push_poke->Pos.y;
			//タッチタイプで汗の位置かえる
			prm = PTFrame_GetPkthlnParam(work, i/ENTRY_MAX, i%ENTRY_MAX);
			switch (prm->Touch){
			case 1:
				mat.y -= (8*FX32_ONE);
				break;
			case 2:
				mat.y -= (8*FX32_ONE);
				break;
			case 3:
				mat.y -= (16*FX32_ONE);
				break;
			default:
				GF_ASSERT(0);
			}
			act_ptr = PkthlnClAct_GetClActWorkPtr(push_poke->SweatActPtr);
			CLACT_SetMatrix(act_ptr, &mat);
		}

		//ポケモン位置
		{
			POKE_ACT_PTR poke_ptr = PokeAct_GetPokeActPtr(ptr->PokeActCntPtr, i);
			//向きセット
			PokeAct_SetDir(poke_ptr, dir);
			//アクター位置セット
			PokeAct_SetPosTouch(poke_ptr, draw_x, draw_y, TRUE);

			//自分のポケの場合はローカルエフェクトオフセット分足しこむ
			if (i/ENTRY_MAX == my_net_id){
				const POKE_SPEC *spec;
				spec = PTFrame_GetPokeSpec(work, my_net_id, i%ENTRY_MAX);
				if (spec->Jump != 0){		//ジャンプしてもいいポケの場合のみ
					PokeAct_Move(poke_ptr, 0, ptr->LocalEff.PokeJumpOfs, dir, FALSE);
				}
			}
		}

		if (pause){
			POKE_ACT_PTR poke_ptr = PokeAct_GetPokeActPtr(ptr->PokeActCntPtr, i);
			CLACT_SetAnmFlag(clact_ptr,0);
			ptr->LocalEff.Pause = 1;
			PointJump(work, &ptr->LocalEff, poke_ptr, i, dir);
		}else{
			CLACT_SetAnmFlag(clact_ptr,1);
		}

		{
			//ポイントフラグがたっているなら、ポイント表示開始
			if (score == i){
				if ((1<=get_score_no)&&(get_score_no<=4)){
					//アニメセット
					CLACT_WORK_PTR clact_ptr;
					clact_ptr = PkthlnClAct_GetClActWorkPtr(push_poke->PointActPtr);
					PkthlnClAct_SetActive(push_poke->PointActPtr, TRUE, TRUE);
					CLACT_AnmChg( clact_ptr, MAIN_PT_ANM_OFS+get_score_no-1 );
					//ポイント取得ＳＥ
					if (get_score_no <=2){
						Snd_SePlay( SE_THLON_POINT1 );
					}else if(get_score_no == 3){
						Snd_SePlay( SE_THLON_POINT2 );
					}else{		//get_score_no == 4
						Snd_SePlay( SE_THLON_POINT3 );
					}
					//サブ画面にポイント加算エフェクト
					PushSub_StartPointEff(ptr->SubDispCntPtr, i / ENTRY_MAX, get_score_no);
					//ポイント取得ジャンプアクション
					SetPointJump(&ptr->LocalEff, i);
				}else{
					GF_ASSERT(0);
				}
			}
		}

		//自分のポケのときのみサークル内チェック
		if ( i/ENTRY_MAX == my_net_id ){		//自分のポケ
			u8 ring_no;		//中身は使用しない
			int sx,sy;
			//影の位置を取得
			PokeAct_GetShadowPosByTouchPos(push_poke->PokeActPtr, x, y, &sx, &sy);
			if ( (state==POKE_ALIVE) &&PtRing_GetPoint(ptr->NowFieldType,	sx, sy, &ring_no) ){
				//サークル内カーソル
				PTFrame_ChgPosMarker( work, i%ENTRY_MAX, 1 );
			}else{
				//ノーマルカーソル
				PTFrame_ChgPosMarker( work, i%ENTRY_MAX, 0 );
			}
		}
	}//end for

	//ポケプライオリティ
	SortPoke(ptr, parent);

	//ローカルエフェクト強制終了処理
	if ( (ptr->LocalEff.Pause)&&(!pause) ){
///		OS_Printf("ローカルエフェクトを強制終了\n");
		StopLocalEff(&ptr->LocalEff);
	}

	//スコア更新処理
	PushSub_ScoreUpdate(ptr->SubDispCntPtr, total_score, net_id);

	//デモ表示
	PushSub_PlayDemoMain(ptr->SubDispCntPtr, pause, fall_list);

}

//----------------------------------------------------------------------------
/**
 *	@brief	ポケモン移動
 *
 *	@param	work	ポケスロンポインタ
 *
 *	@return none
 */
//-----------------------------------------------------------------------------
static void MovePoke(PKTHLN_PTR work)
{
	int i,j;
	PKTHLN_PUSH_PTR ptr = PTFrame_GetEventWorkPtr(work);

	//場外チェック
	for (i=0;i<PUSH_EVENT_POKE_NUM;i++){
		PUSH_POKE *push_poke;
		push_poke = &ptr->Poke[i/ENTRY_MAX][i%ENTRY_MAX];

		//プラスパワー寿命減算処理
		if (push_poke->PlusPower!=0){
			push_poke->PowerLifeTime--;
			if (push_poke->PowerLifeTime <= 0){
				push_poke->PlusPower = 0;
			}
		}

		if (push_poke->State == POKE_NONE){
			continue;
		}

		{
			//場外判定は影の中心位置とする
			if ( CheckFldOutRange(push_poke->PokeActPtr,
						push_poke->NowPoint.x, push_poke->NowPoint.y) ){
				push_poke->State = POKE_NONE;		//場外
				//疲労状態をクリア
				push_poke->FatCount = 0;
				push_poke->Fatigue = 0;

///				OS_Printf("%dが場外へ！\n",i);

				//アクションポイント加算「落下回数」
				PTFrame_AddActionPoint(	work, i/ENTRY_MAX, i%ENTRY_MAX, ADD_TYPE_FALL, 1 );
				//アクションポイント加算「失敗回数」
				PTFrame_AddActionPoint(	work, i/ENTRY_MAX, i%ENTRY_MAX, ADD_TYPE_FAIL, 1 );
				//アクションポイント加算「自滅回数」
				if (ptr->Suicide[i]){
					PTFrame_AddActionPoint(	work, i/ENTRY_MAX, i%ENTRY_MAX, ADD_TYPE_OWN, 1 );
				}
				//アクションポイント自滅予約フラグクリア
				ptr->Suicide[i] = 0;
			}
		}
	}

	//復活判定
	for(i=0;i<PUSH_EVENT_POKE_NUM;i++){
		BOOL revive;
		PUSH_POKE *push_poke1;
		push_poke1 = &ptr->Poke[i/ENTRY_MAX][i%ENTRY_MAX];
		if (push_poke1->State != POKE_REVIVE){
			continue;
		}
		revive = TRUE;
		for(j=0;j<PUSH_EVENT_POKE_NUM;j++){
			PUSH_POKE *push_poke2;
			if (i==j){
				continue;
			}
			push_poke2 = &ptr->Poke[j/ENTRY_MAX][j%ENTRY_MAX];
			if (push_poke2->State == POKE_NONE){
				continue;
			}
			//接触判定
			if ( CheckCircle( push_poke1, push_poke2 ) ){
				//接触しているので復活不可
				revive = FALSE;
				break;
			}
/**
			if ( CheckCircle( &push_poke1->NowPoint, push_poke1->Range,
						&push_poke2->NowPoint, push_poke2->Range) ){
				//接触しているので復活不可
				revive = FALSE;
				break;
			}
*/
		}
		if (revive){
			//復活
			push_poke1->State = POKE_ALIVE;
		}
	}

	////ポケの移動
	for(i=0;i<PUSH_EVENT_POKE_NUM;i++){
		float move;
		PUSH_POKE *push_poke;
		VecFx32 dir_vec;
		VecFx32 norm_dir_vec;
		fx32 len;
		VecFx32 temp_vec;

		push_poke = &ptr->Poke[i/ENTRY_MAX][i%ENTRY_MAX];

		//生存していなければ処理を飛ばす
		if (push_poke->State == POKE_NONE){
			continue;
		}

		//押し込み状態をクリア
		push_poke->Push = 0;
		//推進ベクトルのクリア
		push_poke->MoveVec.x = 0;
		push_poke->MoveVec.y = 0;
		push_poke->MoveVec.z = 0;

		temp_vec = push_poke->NowPoint;
		//方向ベクトル取得
		VEC_Subtract( &push_poke->LastPoint, &temp_vec, &dir_vec );
		//方向ベクトルの長さを取得
		len = VEC_Mag(&dir_vec);

		//長さが0のときは処理を打ち切る
		if (len <= 0){		//動いていない
			//スタミナの回復
			RecoverStamina(push_poke);
			continue;
		}
		//正規化
		VEC_Normalize(&dir_vec, &norm_dir_vec);

		if (push_poke->Fatigue){	//疲労中は一律0.5
			move = 0.5;
		}else{
			move = ((float)push_poke->Param.Move / 10.0);	//<<<	1/10にして使用
		}

		//方向ベクトルの長さが、スピード長以下ならば、次の加算で目的に到達する
		if (len <= FX32_ONE*move){
			temp_vec = push_poke->LastPoint;
		}else{
			//スピード調整
			{
				VecFx32 add = {0,0,0};
				VEC_MultAdd( FX32_ONE*move, &norm_dir_vec, &add, &dir_vec);
				VEC_Add( &dir_vec, &temp_vec, &temp_vec);
			}
		}

		//方向ベクトルから、ポケモンの向きを決定する
		if (len != 0){
			//ZX平面で考える
			u16 rad;
			VecFx32 vec = {0,0,FX32_ONE};
			VecFx32 xz_vec;
			xz_vec.x = norm_dir_vec.y;
			xz_vec.z = norm_dir_vec.x;
			xz_vec.y = 0;

			rad = GetRad(&vec, &xz_vec);
///			OS_Printf("rad=%x\n",rad);
			if ( (0<=rad&&rad<=0x2000)||(0xe000<=rad) ){		//右
				push_poke->Dir = POKE_DIR_RIGHT;
			}else if(0x2000<rad&&rad<0x6000){		//下
				push_poke->Dir = POKE_DIR_DOWN;
			}else if(0x6000<=rad&&rad<=0xa000){		//左
				push_poke->Dir = POKE_DIR_LEFT;
			}else{	//(0xa000<rad&&rad<0xe000)		//上
				push_poke->Dir = POKE_DIR_UP;
			}
		}

		//移動できるかを調べる
		if (push_poke->State == POKE_ALIVE){
			if ( !CheckMovable(ptr, push_poke, i, &dir_vec) ){
				//動けない
				VecFx32 add = {0,0,0};

				//疲労していると押し込めない
				if (push_poke->Fatigue){
///					OS_Printf("疲労中：%d\n",i);
				}else{
					//押し込み状態になる
					push_poke->Push = 1;

					//トルクを決定
					{
						float power;
						power = (float)push_poke->Param.Power / 10.0;	//<<<	1/10にして使用
						//プラスパワーを加味する
						power += push_poke->PlusPower;
						VEC_MultAdd( FX32_ONE*power, &norm_dir_vec, &add, &push_poke->MoveVec);
					}

					if (push_poke->Param.StaminaNow!=0){
						//スタミナ消費
						push_poke->Param.StaminaNow--;
					}else{
						GF_ASSERT(0);
					}
				}
			}else{	//通常移動
				//スタミナの回復
				RecoverStamina(push_poke);
				push_poke->NowPoint = temp_vec;
			}
		}else{	//push_poke->State == POKE_REVIVE
			push_poke->Param.StaminaNow=0;
			push_poke->NowPoint = temp_vec;
		}
	}
	PushExecute(ptr);
}

//----------------------------------------------------------------------------
/**
 *	@brief	最終目的地取得
 *
 *	@param	inTpX		タッチＸ座標
 *	@param	inTpY		タッチＹ座標
 *	@param	*inNowPoint	現在ポイント
 *	@param	inRange		タッチ有効半径
 *	@param	*outPoint	最終目的ポイント
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void GetLastPoint(const u8 inTpX, const u8 inTpY, const VecFx32 *inNowPoint, const fx32 inRange, VecFx32 *outPoint)
{
	VecFx32 vec;
	vec.x = inTpX*FX32_ONE;
	vec.y = inTpY*FX32_ONE;
	vec.z = 0;

	VEC_Subtract( &vec, inNowPoint, &vec );
	//タッチ位置が、ポケモンレンジ外ならば、最終目的地とみなす
	if ( VEC_Mag( &vec ) > inRange ){
		outPoint->x = inTpX*FX32_ONE;
		outPoint->y = inTpY*FX32_ONE;
		outPoint->z = 0;
	}
}

#if 0
//----------------------------------------------------------------------------
/**
 *	@brief	生存ポケ数とプレーヤー数を取得
 *
 *	@param	ptr
 *	@param	*outPlayerNum
 *	@param	*outPokeNum
 *
 *	@return
 */
//-----------------------------------------------------------------------------
static void GetAlivePokeAndPlayerNum(PKTHLN_PUSH_PTR ptr, u8 *outPlayerNum, u8 *outPokeNum)
{
	int i,j;
	u8 tmp;
	PUSH_POKE *push_poke;

	*outPokeNum = PUSH_EVENT_POKE_NUM;
	*outPlayerNum = ENTRY_MEMBER_NUM_MAX;
	//プレーヤー数ループ
	for(i=0;i<ENTRY_MEMBER_NUM_MAX;i++){
		tmp = 0;
		//1プレーヤーのポケ数ループ
		for(j=0;j<ENTRY_MAX;j++){
			push_poke = &ptr->Poke[i][j];
			if (push_poke->State == POKE_NONE){
				tmp++;
			}
		}
		//気絶数分引く
		(*outPokeNum)-=tmp;
		if (tmp == ENTRY_MAX){
			//プレーヤー減らす
			(*outPlayerNum)--;
		}
	}
}
#endif

//----------------------------------------------------------------------------
/**
 *	@brief	ポケモンをタッチしているかを判定する
 *
 *	@param	ptr		競技ポインタ
 *	@param	inNetID	ネットID
 *	@param	inX		X座標
 *	@param	inY		Y座標
 *
 *	@return u8 タッチしたポケモンインデックス
 */
//-----------------------------------------------------------------------------
static u8 CheckPokeTouch(PKTHLN_PUSH_PTR ptr, const u8 inNetID, const u16 inX, const u16 inY)
{
	u8 i;
	u8 touch_list[ENTRY_MAX];
	fx32 touch_range[ENTRY_MAX];
	u8 hit_num;
	u8 target;
	int base_range;
	fx32 now_range;

	base_range = PTFrame_GetPokeTouchRange();
	now_range = base_range*FX32_ONE;
	hit_num =0;
	//タッチしているポケモンのリストを作成
	for (i=0;i<ENTRY_MAX;i++){
		fx32 range;
		int x,y;
		PUSH_POKE *push_poke;
		push_poke = &ptr->Poke[inNetID][i];

		x = push_poke->NowPoint.x / FX32_ONE;
		y = push_poke->NowPoint.y / FX32_ONE;

		if ( PTFrame_CheckTouchRange( x, y, inX, inY, base_range, &range) ){
			//タッチ
			touch_range[i] = range;
			touch_list[i] = 1;
			hit_num++;
		}else{
			touch_range[i] = 0;
			touch_list[i] = 0;
		}
	}

	if (hit_num == 0){
		return PUSH_EVENT_POKE_NUM;		//タッチ範囲外
	}

	target = ENTRY_MAX;
	for (i=0;i<ENTRY_MAX;i++){
		if (touch_list[i]){
			if (touch_range[i] < now_range){
				target = i;
				now_range = touch_range[i];
			}
		}
	}
	if (target==ENTRY_MAX){
		GF_ASSERT(0);
		return PUSH_EVENT_POKE_NUM;
	}

	OS_Printf("target = %d\n",target);

	return (inNetID*ENTRY_MAX)+target;

#if 0
	for(i=0;i<ENTRY_MAX;i++){
		PUSH_POKE *push_poke;
		push_poke = &ptr->Poke[inNetID][i];
		if (push_poke->State == POKE_NONE){
			continue;
		}

		if ( PokeAct_CheckTouch(push_poke->PokeActPtr,
					push_poke->NowPoint.x, push_poke->NowPoint.y, inX, inY) ){
			//タッチしている
			OS_Printf("%dのポケにタッチ\n",i);
			return (inNetID*ENTRY_MAX + i);
		}
	}
	return PUSH_EVENT_POKE_NUM;
#endif
}

//----------------------------------------------------------------------------
/**
 *	@brief	円同士の当たり判定
 *
 *	@param	* poke1	ポケ1
 *	@param	* poke2	ポケ2
 *
 *	@return	TRUEでヒット
 */
//-----------------------------------------------------------------------------
static BOOL CheckCircle(PUSH_POKE * poke1, PUSH_POKE * poke2)
{
	int r1;
	int r2;
	fx32 len;
	VecFx32 vec, vec1, vec2;
	fx32 range;

	PokeAct_GetHitData(poke1->PokeActPtr,
			poke1->NowPoint.x, poke1->NowPoint.y, &vec1.x, &vec1.y, &r1);
	PokeAct_GetHitData(poke2->PokeActPtr,
			poke2->NowPoint.x, poke2->NowPoint.y, &vec2.x, &vec2.y, &r2);

	range = (r1+r2)*FX32_ONE;

	vec1.z = 0;
	vec2.z = 0;

	VEC_Subtract( &vec1, &vec2, &vec );
	//方向ベクトルの長さを取得
	len = VEC_Mag(&vec);

	if (len <= range){
		return TRUE;
	}
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	隣接情報データの作成
 *
 *	@param	ptr	競技ポインタ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void MakeConectData(PKTHLN_PUSH_PTR ptr)
{
	u8 i,j;

	for (i=0;i<PUSH_EVENT_POKE_NUM;i++){
		for (j=0;j<PUSH_EVENT_POKE_NUM;j++){
			PUSH_POKE *push_poke1;
			PUSH_POKE *push_poke2;
			if (i==j){
				//自分自身のデータはつくらない
				ConectData[i].Item[j].Valid = FALSE;
				ConectData[i].Item[j].Poke = NULL;
				continue;
			}
			if (j<i){
				//チェック済み
				continue;
			}
			push_poke1 = &ptr->Poke[i/ENTRY_MAX][i%ENTRY_MAX];
			push_poke2 = &ptr->Poke[j/ENTRY_MAX][j%ENTRY_MAX];

			if ((push_poke1->State != POKE_ALIVE)||(push_poke2->State != POKE_ALIVE)){
				//接触していない
				ConectData[i].Item[j].Valid = FALSE;
				ConectData[j].Item[i].Valid = FALSE;
				ConectData[i].Item[j].Poke = NULL;
				ConectData[j].Item[i].Poke = NULL;
			}else{
				//接触判定
				if ( CheckCircle( push_poke1, push_poke2 ) ){
					//接触してる
					ConectData[i].Item[j].Valid = TRUE;
					ConectData[j].Item[i].Valid = TRUE;
					ConectData[i].Item[j].Poke = push_poke2;
					ConectData[j].Item[i].Poke = push_poke1;
				}else{
					//接触していない
					ConectData[i].Item[j].Valid = FALSE;
					ConectData[j].Item[i].Valid = FALSE;
					ConectData[i].Item[j].Poke = NULL;
					ConectData[j].Item[i].Poke = NULL;
				}
			}
		}
	}
}

//----------------------------------------------------------------------------
/**
 *	@brief	移動できるかを調べる
 *
 *	@param	ptr			競技ポインタ
 *	@param	*poke		対象ポケ
 *	@param	inIdx		ポケインデックス
 *	@param	*inMoveVec	移動ベクトル
 *
 *	@return	TRUEで移動可
 */
//-----------------------------------------------------------------------------
static BOOL CheckMovable(PKTHLN_PUSH_PTR ptr, PUSH_POKE *poke, const u8 inIdx, const VecFx32 *inMoveVec)
{
	u8 i;
	for(i=0;i<PUSH_EVENT_POKE_NUM;i++){
		if ( ConectData[inIdx].Item[i].Valid ){
			//中心間ベクトルと移動方向ベクトルの内積をみて移動可かを決定
			VecFx32 vec;
			VEC_Subtract(&ConectData[inIdx].Item[i].Poke->NowPoint, &poke->NowPoint, &vec );
			if ( VEC_DotProduct(inMoveVec, &vec) > 0 ){	//0より大きければ、移動方向で衝突する
				//移動方向で衝突
				return FALSE;		//動けない
			}
		}
	}

	return TRUE;
}


//----------------------------------------------------------------------------
/**
 *	@brief	コネクト情報を使って、自分の進行パラメータを伝播させる
 *
 *	@param	ptr		競技ポインタ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void PushExecute(PKTHLN_PUSH_PTR ptr)
{
	NODE_DATA Data[PUSH_EVENT_POKE_NUM];		//ノード実体
	u8 move_list[PUSH_EVENT_POKE_NUM];
	u8 ring_hit_check[PUSH_EVENT_POKE_NUM];	//子が親に衝突するときは、動かないようにするためのチェックバッファ
	u8 move_num;
	STACK_DATA stack;	//スタック
	u8 target;
	BOOL push_flg;
	u8 i,n;

	VecFx32 mov_vecs[PUSH_EVENT_POKE_NUM][PUSH_EVENT_POKE_NUM];		//推進ベクトル

	VecFx32 dir_vecs[PUSH_EVENT_POKE_NUM];		//押し込み前の全ポケの移動方向

	move_num = 0;
	//現時点で、移動しているポケの列挙
	for (i=0;i<PUSH_EVENT_POKE_NUM;i++){
		PUSH_POKE *push_poke = &ptr->Poke[i/ENTRY_MAX][i%ENTRY_MAX];
		if ( (push_poke->Push)&&(push_poke->State == POKE_ALIVE) ){
			//追加
			move_list[move_num++] = i;
		}
		VEC_Subtract( &push_poke->LastPoint, &push_poke->NowPoint, &dir_vecs[i] );	//押し込み前移動方向保存
	}

	if (move_num == 0){
		return;
	}

	//移動数をプリント
///	OS_Printf("move_num = %d\n",move_num);

	MI_CpuClear32( mov_vecs, sizeof(VecFx32)*PUSH_EVENT_POKE_NUM*PUSH_EVENT_POKE_NUM);

	//作ったリストを順番に処理
	for (n=0;n<move_num;n++){
		VecFx32 *target_vec;
		VecFx32 move_vec;
		//ターゲット決定
		target = move_list[n];
		//スタックの初期化
		stack.Point = 0;
		//コネクトデータの伝播情報をクリア
		MI_CpuClear8( Data, sizeof(NODE_DATA)*PUSH_EVENT_POKE_NUM);
		//推進ベクトルアドレスセット
		for(i=0;i<PUSH_EVENT_POKE_NUM;i++){
			Data[i].Vec = &(mov_vecs[n][i]);
		}

		//リングヒットチェックバッファのクリア
		MI_CpuClear8( ring_hit_check, sizeof(u8)*PUSH_EVENT_POKE_NUM);

		//ターゲットの推進ベクトルセット
		move_vec = ptr->Poke[target/ENTRY_MAX][target%ENTRY_MAX].MoveVec;

		push_flg = TRUE;
		do{
			//ターゲットの現在地点セット
			target_vec = &ptr->Poke[target/ENTRY_MAX][target%ENTRY_MAX].NowPoint;

			//リングヒットにチェック
			ring_hit_check[target] = 1;

			//推進ベクトル表示
///			OS_Printf("move_vec::%x,%x\n",move_vec.x, move_vec.y);

			if (push_flg){	//プッシュされた場合
				//合成による二度以上の同じノード作成がありえるので、推進ベクトル以外を初期化
				Data[target].ChildNum = 0;
				Data[target].Count = 0;
				//コネクトデータから子を検出。進行方向に影響を及ぼさないアイテムは、伝播対象からはずす
				for (i=0;i<PUSH_EVENT_POKE_NUM;i++){
					if (ConectData[target].Item[i].Valid){
						//コネクトはしている。伝播するかを調べる
						//中心間ベクトルと移動方向ベクトルの内積をみて移動可かを決定
						VecFx32 vec;
						VEC_Subtract(&ConectData[target].Item[i].Poke->NowPoint, target_vec, &vec );
						if ( VEC_DotProduct(&move_vec, &vec) > 0 ){	//0より大きければ、移動方向で衝突する
							u8 set_idx;
							set_idx = i;
							//エントリー
							Data[target].Child[Data[target].ChildNum] = set_idx;
							Data[target].ParToChld[Data[target].ChildNum] = vec;
							Data[target].ChildNum++;
						}
					}
				}//end for
/**
				//接続状態をプリント
				{
					u8 d;
					OS_Printf("parent=%d\n",target);
					for(d=0;d<Data[target].ChildNum;d++){
						OS_Printf("Child = %d\n",Data[target].Child[d]);
					}
				}
*/
				//推進ベクトルをアッド
				VEC_Add( Data[target].Vec, &move_vec, Data[target].Vec);
			}//end if(push_flg)

			push_flg = FALSE;

///			OS_Printf("%d/%d",Data[target].Count,Data[target].ChildNum);

			//自分に付属している子をすべて処理したか？
			if(Data[target].Count >= Data[target].ChildNum){		//子をすべて処理
				//リングヒットチェックオフ
				ring_hit_check[target] = 0;
				//親に戻る(スタックのポップ)
				target = PopData(&stack);
			}else{		//まだ
				u8 rc;
				u8 next;

				next = Data[target].Child[ Data[target].Count ];
				if (ring_hit_check[next]){
///					OS_Printf("リングヒットしてるので、伝播を中止！\n");
					Data[target].Count++;
				}else{
					//データをプッシュ
					rc = PushData(&stack, target);

					//エラー対処
					if (rc == DATA_NONE){
						break;
					}

					if (GetCos( Data[target].Vec, &Data[target].ParToChld[Data[target].Count] ) >= FX_CosIdx(0x2000)){
						//推進ベクトルを分解せず子に引き継ぐ
						move_vec = *Data[target].Vec;
					}else{
						//推進ベクトルを分解して子に引き継ぐ
						CalcVec(Data[target].Vec, &Data[target].ParToChld[Data[target].Count], &move_vec);
					}
					//次の子インデックスを取得
					target = Data[target].Child[ Data[target].Count++ ];
					//ノード作成ルーチンに通す
					push_flg = TRUE;
				}
			}
		}while(target != DATA_NONE);	//スタックが空になるまで
/**
		//データのプリント
		{
			u8 d;
			for(d=0;d<PUSH_EVENT_POKE_NUM;d++){
				OS_Printf("vec_len:%x\n",VEC_Mag(Data[d].Vec));
				OS_Printf("push_move_vec = %x,%x\n", Data[d].Vec->x, Data[d].Vec->y);
			}
		}
*/
	}	//end for (n=0;n<move_num;n++)


	//データができたら、それぞれのポケに移動を適用させる
	for (n=0;n<move_num;n++){
		PUSH_POKE *target_poke;
		for (i=0;i<PUSH_EVENT_POKE_NUM;i++){
			PUSH_POKE *poke = &ptr->Poke[i/ENTRY_MAX][i%ENTRY_MAX];
			VEC_Add( &poke->NowPoint,
					 &(mov_vecs[n][i]),
					 &poke->NowPoint);
			//押し込みによって動いて、かつ押し込み状態でないものは最終目的地を更新
			if ( (VEC_Mag(&mov_vecs[n][i]) != 0)&&(poke->Push==0) ){
				poke->LastPoint = poke->NowPoint;
			}
		}
		target = move_list[n];
		target_poke = &ptr->Poke[target/ENTRY_MAX][target%ENTRY_MAX];
		//持続力を使い切った場合・・・
		if (target_poke->Param.StaminaNow == 0){
			int idx;
			//ホールドされてる場合は解除
			for(idx=0;idx<ENTRY_MEMBER_NUM_MAX;idx++){
				if (target == ptr->HoldPokeNo[idx]){
					ptr->HoldPokeNo[idx] = PUSH_EVENT_POKE_NUM;
					break;
				}
			}
			//疲労状態
			GF_ASSERT(target_poke->State == POKE_ALIVE);
			target_poke->Fatigue = 1;
			//疲労カウンタセット
			target_poke->FatCount = FATIGUE_COUNT;
			//その場でストップ
			target_poke->LastPoint = target_poke->NowPoint;
			target_poke->MoveVec.x = 0;
			target_poke->MoveVec.y = 0;
			//押し込みクリア
			target_poke->Push = 0;
		}
	}

	//現在位置と目的地を結ぶベクトルと押し込み前の移動方向ベクトルの内積が０未満のときは、
	//目的地を通り過ぎたとみなし、目的地の書き換えを行う
	for(i=0;i<PUSH_EVENT_POKE_NUM;i++){
		VecFx32 dir_vec;
		PUSH_POKE *poke = &ptr->Poke[i/ENTRY_MAX][i%ENTRY_MAX];
		VEC_Subtract( &poke->LastPoint, &poke->NowPoint, &dir_vec );
		if ( VEC_DotProduct(&dir_vecs[i], &dir_vec) < 0 ){
			poke->LastPoint = poke->NowPoint;
		}
	}
}

//----------------------------------------------------------------------------
/**
 *	@brief	データのプッシュ
 *
 *	@param	*Stack		スタック
 *	@param	inData		積むデータ
 *
 *	@return	u8 スタックインデックス
 */
//-----------------------------------------------------------------------------
static u8 PushData(STACK_DATA *Stack, const u8 inData)
{
	u8 idx;
	GF_ASSERT(Stack->Point < PUSH_EVENT_POKE_NUM);

	if (Stack->Point >= PUSH_EVENT_POKE_NUM){
		return DATA_NONE;
	}

	idx = Stack->Point++;
	Stack->Data[idx] = inData;
///	OS_Printf("PUSH:%d_TO_%d\n",inData, idx);
	return idx;
}

//----------------------------------------------------------------------------
/**
 *	@brief	データのポップ
 *
 *	@param	*Stack		スタック
 *
 *	@return	u8 スタックインデックス
 */
//-----------------------------------------------------------------------------
static u8 PopData(STACK_DATA *Stack)
{
	if (Stack->Point-1 < 0){
///		OS_Printf("スタックが空\n");
		return DATA_NONE;
	}
///	OS_Printf("POP:%d_FROM_%d\n",Stack->Data[Stack->Point-1],Stack->Point-1);

	return Stack->Data[--Stack->Point];
}

//----------------------------------------------------------------------------
/**
 *	@brief	推進ベクトルを分解して子に引き継ぐ
 *
 *	@param	*inVec1		入力ベクトル1
 *	@param	*inVec2		入力ベクトル2
 *	@param	*outVec		移動ベクトル
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void CalcVec(const VecFx32 *inVec1, const VecFx32 *inVec2, VecFx32 *outVec)
{
	VecFx32 vec1,vec2;
	fx32 cos,len1,len2;

	VEC_Normalize(inVec1, &vec1);
	VEC_Normalize(inVec2, &vec2);

	cos = VEC_DotProduct(&vec1, &vec2);
	len1 = VEC_Mag(inVec1);
	len2 = FX_Mul(cos, len1);
	{
		VecFx32 vec = {0,0,0};
		VEC_MultAdd( len2, &vec2, &vec, outVec);
	}
///	OS_Printf("length = %x:%x\n",len1,len2);
}

//----------------------------------------------------------------------------
/**
 *	@brief	コサイン取得
 *
 *	@param	inVec1	ベクトル1
 *	@param	inVec2	ベクトル2
 *
 *	@return fx32 コサイン
 */
//-----------------------------------------------------------------------------
static fx32 GetCos( const VecFx32 *inVec1, const VecFx32 *inVec2 )
{
	VecFx32 vec1,vec2;

	VEC_Normalize(inVec1, &vec1);
	VEC_Normalize(inVec2, &vec2);

	return VEC_DotProduct(&vec1, &vec2);
}

//----------------------------------------------------------------------------
/**
 *	@brief	得点取得判定
 *
 *	@param	ptr		競技ポインタ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void CheckScore(PKTHLN_PUSH_PTR ptr)
{
	int i;
	u8 point;
	u8 ring_no;

	u8 point_hash[RING_MAX][PUSH_EVENT_POKE_NUM];
	u8 score_hash[RING_MAX];
	u8 ring_idx[RING_MAX];

	if (!ptr->AddScoreReq){
		return;
	}

	for(i=0;i<RING_MAX;i++){
		ring_idx[i] = 0;
	}

	ptr->AddScoreReq = 0;

///	OS_Printf("リング内外判定と得点加算\n");

	//ポイントリスト初期化(配列数をクリア)
	ptr->PointUpNumMax = 0;
	ptr->PointUpNum = 0;

	for(i=0;i<PUSH_EVENT_POKE_NUM;i++){
		PUSH_POKE *poke = &ptr->Poke[i/ENTRY_MAX][i%ENTRY_MAX];
		if (poke->State == POKE_ALIVE){
			int x,y;
			int sx,sy;
			//影の位置を取得
			x = poke->NowPoint.x/FX32_ONE;
			y = poke->NowPoint.y/FX32_ONE;
			PokeAct_GetShadowPosByTouchPos(poke->PokeActPtr, x, y, &sx, &sy);
			point = PtRing_GetPoint(ptr->NowFieldType,
					sx, sy, &ring_no);
			if (point){
				poke->Score+=point;
				point_hash[ring_no][ ring_idx[ring_no]++ ] = i;
				score_hash[ring_no] = point;
			}
		}
	}

	for(i=0;i<RING_MAX;i++){
		int j;
		for(j=0;j<ring_idx[i];j++){
			//ポイントリストに格納
			ptr->PointUpList[ptr->PointUpNumMax] = point_hash[i][j];
			ptr->PointList[ptr->PointUpNumMax] = score_hash[i];
			ptr->PointUpNumMax++;
		}
	}
}

//タイマー画面更新関連

//----------------------------------------------------------------------------
/**
 *	@brief	タイマーBGのフィル
 *
 *	@param	inTime	タイマー
 *	@param	*bgl	BGL
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void FillTimerBG(const u8 inTime, GF_BGL_INI *bgl)
{
	int i;
	for(i=1;i<=inTime;i++){
		Fill(i, bgl);
	}
	GF_BGL_LoadScreenV_Req(bgl, GF_BGL_FRAME1_M);
}

//----------------------------------------------------------------------------
/**
 *	@brief		フィル処理
 *
 *	@param	inTime	タイマー
 *	@param	*bgl	BGL
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void  Fill(const u8 inTime, GF_BGL_INI *bgl)
{
	int x,y;
	//フィル対処のXYを求める
	if ( (1<=inTime)&&(inTime<=6) ){
		x = 18+(inTime-1)*2;
		y = 2;
	}else if( (16<=inTime)&&(inTime<=28) ){
		x = 26-(inTime-16)*2;
		y = 20;
	}else if( (38<=inTime)&&(inTime<ONE_CYCLE_TIME) ){
		x = 4+(inTime-38)*2;
		y = 2;
	}else if ( (7<=inTime)&&(inTime<=15) ){
		x = 28;
		y = 4+(inTime-7)*2;
	}else{
		x = 2;
		y = 18-(inTime-29)*2;
	}
	//フィル
	GF_BGL_ScrFill( bgl, GF_BGL_FRAME1_M, 0, x, y, 2, 2, GF_BGL_SCRWRT_PALNL );
}

//----------------------------------------------------------------------------
/**
 *	@brief	ポケ復活処理
 *
 *	@param	ptr	競技ポインタ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void RevivePoke(PKTHLN_PUSH_PTR ptr)
{
	int i,j;
	for(i=0;i<ENTRY_MEMBER_NUM_MAX;i++){
		for(j=0;j<ENTRY_MAX;j++){
			PUSH_POKE	*poke;
			poke = &ptr->Poke[i][j];
			if (poke->State == POKE_NONE){
				poke->State = POKE_REVIVE;
				//復活位置に移動
				{
					int x,y;
					PokeAct_GetTouchPosByShadowPos(poke->PokeActPtr,
									InitPos[i][j].X, InitPos[i][j].Y, &x, &y);
					poke->NowPoint.x = x*FX32_ONE;
					poke->NowPoint.y = y*FX32_ONE;
///					OS_Printf("%d::復活位置：%d,%d\n",i,x,y);
				}
				poke->LastPoint = poke->NowPoint;
				//向きセット
				poke->Dir = POKE_DIR_DOWN;
			}
		}
	}
}

//----------------------------------------------------------------------------
/**
 *	@brief	対象ネットIDのポケリタイア判定
 *
 *	@param	ptr			競技ポインタ
 *	@param	inNetID		ネットＩＤ
 *
 *	@return	TRUEで３匹とも操作不可
 */
//-----------------------------------------------------------------------------
static BOOL IsRetire(PKTHLN_PUSH_PTR ptr, const int inNetID)
{
	int i;
	for(i=0;i<ENTRY_MAX;i++){
		if (ptr->Poke[inNetID][i].State != POKE_NONE){
			return FALSE;	//何かしら動かせる状態
		}
	}
	return TRUE;	//3匹とも操作不可
}

//--------------------------------------------------------------------------------------------
/**
 *　スタミナ回復
 *
 * @param	outPoke		対象ポケデータポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void RecoverStamina(PUSH_POKE *outPoke)
{
	if (outPoke->Fatigue){		//疲労状態
		//疲労状態カウンタ減算
		outPoke->FatCount--;
		if (outPoke->FatCount<=0){	//疲労回復
			outPoke->FatCount = 0;
			outPoke->Fatigue = 0;
			outPoke->Param.StaminaNow = outPoke->Param.StaminaMax;
		}
	}else{
		outPoke->Param.StaminaNow += RECOV_VAL;
		if (outPoke->Param.StaminaNow > outPoke->Param.StaminaMax){
			outPoke->Param.StaminaNow = outPoke->Param.StaminaMax;
		}
		if (outPoke->Param.StaminaNow == outPoke->Param.StaminaMax){
			//疲労状態回復
			outPoke->FatCount = 0;
			outPoke->Fatigue = 0;
		}
	}
}

//--------------------------------------------------------------------------------------------
/**
 * パラメータセット
 *
 * @param	work		ポケスロンワークポインタ
 * @param	*inData		パラメータ
 * @param	inNetID		ネットＩＤ
 * @param	inIdx		ポケモンエントリーインデックス0〜2
 * @param	*outPoke	パラメータ格納場所
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void SetPokeParam(	PKTHLN_PTR work, const PUSH_PARAM *inData,
							const u8 inNetID, const u8 inIdx, PUSH_POKE *outPoke)
{
	const POKE_SPEC *spec;
	spec = PTFrame_GetPokeSpec(work, inNetID, inIdx);
/**
	OS_Printf("%d::pw:st:sp = %d,%d,%d\n",
			inIdx,inData->Power[spec->Power],inData->Stamina[spec->Stamina],inData->Speed[spec->Speed]);
*/
	outPoke->Param.Power = inData->Power[spec->Power];
	outPoke->Param.StaminaMax = inData->Stamina[spec->Stamina];
	outPoke->Param.StaminaNow = inData->Stamina[spec->Stamina];
	outPoke->Param.Move = inData->Speed[spec->Speed];
}

//--------------------------------------------------------------------------------------------
/**
 * ローカルエフェクトセット
 *
 * @param	local			ローカルエフェクトポインタ
 * @param	inOldFldType	旧フィールドタイプ
 * @param	inNewFldType	新フィールドタイプ
 * @param	work			ポケスロンポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void SetLocalEff(LOCAL_EFF *local, const int inOldFldType, const int inNewFldType, PKTHLN_PTR work)
{
	local->OldFldType = inOldFldType;
	local->NewFldType = inNewFldType;
	local->Seq = 0;
	local->LocalEffTcb = TCB_Add(LocalEffMainTcb, local, 0);
	local->RingAlphaTcb = TCB_Add(RingAlphaTcb, local, 1);
	local->work = work;
	//READY表示ＢＧセット
	G2_SetBG2Offset(0, READY_BG_START_OFS);
	local->ReadyTcb = TCB_Add(ReadyTcb, local, 2);
}

//--------------------------------------------------------------------------------------------
/**
 * ローカル演出タスク
 *
 * @param	tcb			TCB
 * @param	work		ワーク
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void LocalEffMainTcb(TCB_PTR tcb, void* work)
{
	LOCAL_EFF *local;
	local = (LOCAL_EFF*)work;

	switch(local->Seq){
	case 0:
		//ウェイト(TCB終了待ち)
		if(local->ReadyTcb == NULL){
			//ポケジャンプTCB登録(既にある場合は登録しない)
			local->PokeJumpTcb = TCB_Add(PokeJumpTcb, local, 3);
			local->Seq++;
		}
		break;
	case 1:
		if (local->PokeJumpTcb == NULL){
			local->LocalEffTcb = NULL;
			local->Seq = 0;

			//親にローカル演出終了を通達
			{
				PUSH_CHILD_DATA *child_data;
				COMM_EVENT_COMMON_DATA *data;
				data = PTFrame_GetEvtComCmnData(local->work);
				child_data = PKTHLN_CommPack_GetData(&data->SendData);
				child_data->LocalEnd = 1;
			}
			TCB_Delete(tcb);

		}
	}
}

//--------------------------------------------------------------------------------------------
/**
 * リングアルファタスク
 *
 * @param	tcb			TCB
 * @param	work		ワーク
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void RingAlphaTcb(TCB_PTR tcb, void* work)
{
	u16 alpha;
	u8 frame;
	LOCAL_EFF *local;
	local = (LOCAL_EFF*)work;

	switch(local->AlphaSeq){
	case 0:
		local->RingEffFrame++;
		if (local->RingEffFrame <= RING_ALPHA_BLEND_SYNC){
			frame = local->RingEffFrame;
			alpha = (frame*ALPHA_MAX) / RING_ALPHA_BLEND_SYNC;
			//フェードアウト
			G2_SetBlendAlpha( GX_BLEND_PLANEMASK_NONE, GX_BLEND_PLANEMASK_BG0,
					ALPHA_MAX-alpha, alpha+4 );
		}else{
			local->AlphaSeq++;
		}
		break;
	case 1:
		//フィールドタイプを変更
		PtRing_MakeField(local->RingCntPtr, local->NewFldType);
		PtRing_ClearData(local->RingCntPtr, local->OldFldType);
		local->RingEffFrame = 0;
		local->AlphaSeq++;
		Snd_SePlay( SE_PUSH_NEXT_SET );			//サークル変更音
		break;
	case 2:
		local->RingEffFrame++;
		if (local->RingEffFrame <= RING_ALPHA_BLEND_SYNC){
			//フェードイン
			frame = local->RingEffFrame;
			alpha = (frame*ALPHA_MAX) / RING_ALPHA_BLEND_SYNC;
			G2_SetBlendAlpha( GX_BLEND_PLANEMASK_NONE, GX_BLEND_PLANEMASK_BG0,
					alpha, 16-alpha );
		}else{
			local->RingAlphaTcb = NULL;
			local->RingEffFrame = 0;
			local->AlphaSeq = 0;
			TCB_Delete(tcb);
		}
	}
}

//--------------------------------------------------------------------------------------------
/**
 * 「READY」タスク
 *
 * @param	tcb			TCB
 * @param	work		ワーク
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void ReadyTcb(TCB_PTR tcb, void* work)
{
	int frame;
	int ofs;
	LOCAL_EFF *local;
	local = (LOCAL_EFF*)work;

	switch(local->ReadySeq){
	case 0:
		local->ReadyFrame++;
		frame = local->ReadyFrame;
		ofs = READY_BG_START_OFS - (frame*READY_BG_START_OFS)/READY_SCROLL_FRAME;
		//スクロール
		G2_SetBG2Offset(0, ofs);
		if (local->ReadyFrame >= READY_SCROLL_FRAME){
			local->ReadyFrame = 0;
			local->ReadySeq++;
		}
		break;
	case 1:
		local->ReadyFrame++;
		if (local->ReadyFrame >= READY_WAIT_FRAME){
			local->ReadyFrame = 0;
			local->ReadySeq++;
		}
		break;
	case 2:
		local->ReadyFrame++;
		frame = local->ReadyFrame;
		ofs = (frame*READY_BG_END_OFS)/READY_SCROLL_FRAME;
		//スクロール
		G2_SetBG2Offset(0, ofs);
		if (local->ReadyFrame >= READY_SCROLL_FRAME){
			local->ReadyFrame = 0;
			local->ReadyTcb = NULL;
			local->ReadySeq = 0;
			TCB_Delete(tcb);
		}
		break;
	}
}

//--------------------------------------------------------------------------------------------
/**
 * ポケモンジャンプタスク
 *
 * @param	tcb			TCB
 * @param	work		ワーク
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void PokeJumpTcb(TCB_PTR tcb, void* work)
{
	LOCAL_EFF *local;
	local = (LOCAL_EFF*)work;

	local->PokeJumpOfs += PokeJumpArray[local->PokeJumpFrame];


	local->PokeJumpFrame++;

	if (local->PokeJumpFrame >= POKE_JUMP_FRAME){
		local->PokeJumpOfs = 0;
		local->PokeJumpTcb = NULL;
		local->PokeJumpFrame = 0;
		TCB_Delete(tcb);
	}
}

//--------------------------------------------------------------------------------------------
/**
 * ローカルエフェクト中止
 *
 * @param	local		ローカルエフェクトポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
//ローカルエフェクト中止
static void StopLocalEff(LOCAL_EFF *local)
{
	local->Pause = 0;

	//TCBの停止
	if (local->LocalEffTcb!=NULL){
		//強制終了の場合も親にローカル演出終了を通達
		{
			PUSH_CHILD_DATA *child_data;
			COMM_EVENT_COMMON_DATA *data;
			data = PTFrame_GetEvtComCmnData(local->work);
			child_data = PKTHLN_CommPack_GetData(&data->SendData);
			child_data->LocalEnd = 1;
		}
		TCB_Delete(local->LocalEffTcb);
		local->LocalEffTcb = NULL;
	}
	if (local->ReadyTcb!=NULL){
		TCB_Delete(local->ReadyTcb);
		local->ReadyTcb = NULL;
	}
	if (local->RingAlphaTcb!=NULL){
		TCB_Delete(local->RingAlphaTcb);
		local->RingAlphaTcb = NULL;
	}
	if (local->PokeJumpTcb!=NULL){
		TCB_Delete(local->PokeJumpTcb);
		local->PokeJumpTcb = NULL;
	}
	if (local->PointJumpTcb != NULL){
		TCB_Delete(local->PointJumpTcb);
		local->PointJumpTcb = NULL;
	}
	//READY表示ＢＧのオフセット初期化
	G2_SetBG2Offset(0, READY_BG_START_OFS);
	//シーケンス初期化
	local->Seq = 0;
	local->AlphaSeq = 0;
	local->ReadySeq = 0;
	//フレーム関連初期化
	local->RingEffFrame = 0;
	local->ReadyFrame = 0;
	local->PokeJumpFrame = 0;
	local->PointJumpFrame = 0;
	//ローカルポケジャンプ値初期化
	local->PokeJumpOfs = 0;
	local->PointJumpOfs = 0;

	local->PJTarget = PUSH_EVENT_POKE_NUM;

	//リングアルファ値初期化
	G2_SetBlendAlpha( GX_BLEND_PLANEMASK_NONE, GX_BLEND_PLANEMASK_BG0,
					ALPHA_MAX, 16-ALPHA_MAX );
}

//--------------------------------------------------------------------------------------------
/**
 * ポイントジャンプタスクセット
 *
 * @param	local			ローカルエフェクトポインタ
 * @param	inPokeIdx		ポケインデックス
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void SetPointJump(LOCAL_EFF *local, const u8 inPokeIdx)
{
	if (local->PointJumpTcb == NULL){
		local->PJTarget = inPokeIdx;
		local->PointJumpTcb = TCB_Add(PointJumpTcb, local, 0);
	}else{	//通信遅延が発生した場合にここにくる可能性がある
///		GF_ASSERT(0);
		//↑ＴＣＢを複数化すれば解決できるが、現行ではＴＣＢが存在した場合は、タスクセットをスルーするようにしておく2009.03.13
	}
}

//--------------------------------------------------------------------------------------------
/**
 * ポイントジャンプタスク
 *
 * @param	tcb				TCB
 * @param	work			ワーク
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void PointJumpTcb(TCB_PTR tcb, void* work)
{
	LOCAL_EFF *local;
	local = (LOCAL_EFF*)work;

	local->PointJumpOfs += PointJumpArray[local->PointJumpFrame];

	local->PointJumpFrame++;

	if (local->PointJumpFrame >= POINT_JUMP_FRAME){
		local->PointJumpOfs = 0;
		local->PointJumpTcb = NULL;
		local->PointJumpFrame = 0;
		local->PJTarget = PUSH_EVENT_POKE_NUM;
		TCB_Delete(tcb);
	}
}

//--------------------------------------------------------------------------------------------
/**
 * ポイントジャンプ
 *
 * @param	work			ポケスロンポインタ
 * @param	local			ローカルエフェクトポインタ
 * @param	poke_ptr		ポケアクター
 * @param	inPokeIdx		ポケインデックス
 * @param 	inDir			方向
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void PointJump(PKTHLN_PTR work, LOCAL_EFF *local, POKE_ACT_PTR poke_ptr, const u8 inPokeIdx, const POKE_DIR inDir)
{
	//対象ポケか？
	if (local->PJTarget == inPokeIdx){
		const POKE_SPEC *spec;
		spec = PTFrame_GetPokeSpec(work, inPokeIdx/ENTRY_MAX, inPokeIdx%ENTRY_MAX);
		if (spec->Jump != 0){		//ジャンプしてもいいポケの場合のみ
			PokeAct_Move(poke_ptr, 0, local->PointJumpOfs, inDir, FALSE);
		}
	}
}

//--------------------------------------------------------------------------------------------
/**
 * BMPウィンドウ追加
 *
 * @param 	ptr			コントローラポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void CreateBmpWin( PKTHLN_PUSH_PTR ptr )
{
	const BMPWIN_DAT * dat = &RecordBmpData;

	GF_BGL_BmpWinAddEx( ptr->bgl, &ptr->Win, dat );

	//先頭キャラをクリア（スクリーンクリアされてるところは、このキャラで埋まる）
	GF_BGL_CharFill( ptr->bgl, REC_BG, 0, 1, 0 );

	//システム用フォントパレット転送
	SystemFontPaletteLoad(PALTYPE_MAIN_BG, REC_FONT_PAL*32, ptr->HeapID);
}

//----------------------------------------------------------------------------
/**
 *	@brief		レコード文字列展開
 *
 *	@param	ptr		コントローラポインタ
 *	@param	inPoint
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void SetRecordStr(PKTHLN_PUSH_PTR ptr, const int inPoint)
{
	WORDSET *word;
	STRBUF * str;
	MSGDATA_MANAGER *msgman;
	int integer;

	GF_BGL_BmpWinDataFill( &ptr->Win, 0);

	//整数部分
	integer = inPoint;

	msgman = MSGMAN_Create(MSGMAN_TYPE_DIRECT, ARC_MSG, NARC_msg_pokethlon_dat, ptr->HeapID);
    word = WORDSET_Create(ptr->HeapID);
	WORDSET_RegisterNumber(word, 0, integer, 3,
				NUMBER_DISPTYPE_LEFT,NUMBER_CODETYPE_DEFAULT);

    str = MSGDAT_UTIL_AllocExpandString(word, msgman, msg_pkthln_new_record03, ptr->HeapID);

	GF_STR_PrintColor( 	&ptr->Win, FONT_TOUCH, str,
					0, 0, MSG_NO_PUT, COL_N_WHITE, NULL );
	STRBUF_Delete(str);//<一括表示なので、メモリをここで消してもOK
	WORDSET_Delete( word );
	MSGMAN_Delete( msgman );

	GF_BGL_BmpWinOn(&ptr->Win);
}

//----------------------------------------------------------------------------
/**
 *	@brief	場外チェック
 *
 *  @param	poke_ptr	ポケモンアクター
 *	@param	inX			Ｘ座標
 *	@param	inY			Ｙ座標
 *
 *	@return	BOOL		TRUE:場外
 */
//-----------------------------------------------------------------------------
static BOOL CheckFldOutRange(POKE_ACT_PTR poke_ptr, const fx32 inX, const fx32 inY)
{
	int x,y;
	int sx,sy;
	x = inX / FX32_ONE;
	y = inY / FX32_ONE;

	PokeAct_GetShadowPosByTouchPos(poke_ptr, x, y, &sx, &sy);
///			OS_Printf("shadow:%d,%d\n",sx,sy);
	if ( (SIDE_MIN>sx)||(sx>=SIDE_MAX)||
					(HEIGHT_MIN>sy)||(sy>=HEIGHT_MAX) ){
		return TRUE;
	}

	return FALSE;

}

//--------------------------------------------------------------------------------------------
/**
 * ソート用比較関数
 *
 * @param	elem1		要素1
 * @param	elem2		要素2
 * @return	s32
 */
//--------------------------------------------------------------------------------------------
static s32 CompFunc(void *elem1, void *elem2)
{
	s32 ret;
	POKE_SORT_WORK * poke1 = elem1;
	POKE_SORT_WORK * poke2 = elem2;
	if (poke1->Y > poke2->Y){		//要素1の方がY値が高い場合は要素1を前に
		ret = -1;		//要素1が前
	}else if( poke1->Y < poke2->Y ){	//要素2の方がY値が高い場合は要素2を前に
		ret = 1;		//要素2が後
	}else{	//Yの値が同じ場合、割り振られたインデックスの小さい方を優先するようにする
		if (poke1->Idx < poke2->Idx){
			ret = -1;
		}else if(poke1->Idx > poke2->Idx){
			ret = 1;
		}else {
			//※NitroSDKのソート関数のコールバックは自分自身の比較もしているようなので、ここにアサートがあるととまってしまう
			ret = 0;
		}
	}
	return ret;
}

//--------------------------------------------------------------------------------------------
/**
 * ポケソート関数
 *
 * @param	ptr			競技ポインタ
 * @param	parent		受信通信データ
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void SortPoke(PKTHLN_PUSH_PTR ptr, PUSH_PARENT_DATA *parent)
{
	u8 i;
	u32 size;
	POKE_SORT_WORK sort_work[SORT_POKE_MAX];
	for (i=0;i<SORT_POKE_MAX;i++){
		PUSH_POKE *push_poke;
		int sx,sy;
		push_poke = &ptr->Poke[i/ENTRY_MAX][i%ENTRY_MAX];
		sort_work[i].Idx = i;
		PokeAct_GetShadowPosByTouchPos(push_poke->PokeActPtr, parent->PokeX[i], parent->PokeY[i], &sx, &sy);
		sort_work[i].Y = sy;
	}
	size = sizeof(POKE_SORT_WORK);

	MATH_QSort( sort_work,
			    SORT_POKE_MAX,
				size,
				CompFunc,
				ptr->PokeSortBuf );

	for (i=0;i<SORT_POKE_MAX;i++){
		PUSH_POKE *push_poke;
		u8 idx;
		idx = sort_work[i].Idx;
		push_poke = &ptr->Poke[idx/ENTRY_MAX][idx%ENTRY_MAX];
		PokeAct_SetPriority(push_poke->PokeActPtr, PRI_POKE+i);
	}
}
